github.phpd.cn/hashicorp/packer@v1.3.2/panic.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/packer/packer"
    10  	"github.com/mitchellh/panicwrap"
    11  )
    12  
    13  // This is output if a panic happens.
    14  const panicOutput = `
    15  
    16  !!!!!!!!!!!!!!!!!!!!!!!!!!! PACKER CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    17  
    18  Packer crashed! This is always indicative of a bug within Packer.
    19  A crash log has been placed at "crash.log" relative to your current
    20  working directory. It would be immensely helpful if you could please
    21  report the crash with Packer[1] so that we can fix this.
    22  
    23  [1]: https://github.com/hashicorp/packer/issues
    24  
    25  !!!!!!!!!!!!!!!!!!!!!!!!!!! PACKER CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    26  `
    27  
    28  // panicHandler is what is called by panicwrap when a panic is encountered
    29  // within Packer. It is guaranteed to run after the resulting process has
    30  // exited so we can take the log file, add in the panic, and store it
    31  // somewhere locally.
    32  func panicHandler(logF *os.File) panicwrap.HandlerFunc {
    33  	return func(m string) {
    34  		// Write away just output this thing on stderr so that it gets
    35  		// shown in case anything below fails.
    36  		fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", m))
    37  
    38  		if err := packer.CheckpointReporter.ReportPanic(m); err != nil {
    39  			fmt.Fprintf(os.Stderr, "Failed to report panic. This is safe to ignore: %s", err)
    40  		}
    41  
    42  		// Create the crash log file where we'll write the logs
    43  		f, err := os.Create("crash.log")
    44  		if err != nil {
    45  			fmt.Fprintf(os.Stderr, "Failed to create crash log file: %s", err)
    46  			return
    47  		}
    48  		defer f.Close()
    49  
    50  		// Seek the log file back to the beginning
    51  		if _, err = logF.Seek(0, 0); err != nil {
    52  			fmt.Fprintf(os.Stderr, "Failed to seek log file for crash: %s", err)
    53  			return
    54  		}
    55  
    56  		// Copy the contents to the crash file. This will include
    57  		// the panic that just happened.
    58  		if _, err = io.Copy(f, logF); err != nil {
    59  			fmt.Fprintf(os.Stderr, "Failed to write crash log: %s", err)
    60  			return
    61  		}
    62  
    63  		// Tell the user a crash occurred in some helpful way that
    64  		// they'll hopefully notice.
    65  		fmt.Printf("\n\n")
    66  		fmt.Println(strings.TrimSpace(panicOutput))
    67  	}
    68  }