panicHandler is what is called by panicwrap when a panic is encountered within Packer. It is guaranteed to run after the resulting process has exited so we can take the log file, add in the panic, and store it somewhere locally.
(logF *os.File)
| 33 | // exited so we can take the log file, add in the panic, and store it |
| 34 | // somewhere locally. |
| 35 | func panicHandler(logF *os.File) panicwrap.HandlerFunc { |
| 36 | return func(m string) { |
| 37 | // Write away just output this thing on stderr so that it gets |
| 38 | // shown in case anything below fails. |
| 39 | fmt.Fprintf(os.Stderr, "%s", fmt.Sprintf("%s\n", m)) |
| 40 | |
| 41 | if err := packer.CheckpointReporter.ReportPanic(m); err != nil { |
| 42 | fmt.Fprintf(os.Stderr, "Failed to report panic. This is safe to ignore: %s", err) |
| 43 | } |
| 44 | |
| 45 | // Create the crash log file where we'll write the logs |
| 46 | f, err := os.Create("crash.log") |
| 47 | if err != nil { |
| 48 | fmt.Fprintf(os.Stderr, "Failed to create crash log file: %s", err) |
| 49 | return |
| 50 | } |
| 51 | defer f.Close() |
| 52 | |
| 53 | // Seek the log file back to the beginning |
| 54 | if _, err = logF.Seek(0, 0); err != nil { |
| 55 | fmt.Fprintf(os.Stderr, "Failed to seek log file for crash: %s", err) |
| 56 | return |
| 57 | } |
| 58 | |
| 59 | // Copy the contents to the crash file. This will include |
| 60 | // the panic that just happened. |
| 61 | if _, err = io.Copy(f, logF); err != nil { |
| 62 | fmt.Fprintf(os.Stderr, "Failed to write crash log: %s", err) |
| 63 | return |
| 64 | } |
| 65 | |
| 66 | // Tell the user a crash occurred in some helpful way that |
| 67 | // they'll hopefully notice. |
| 68 | fmt.Printf("\n\n") |
| 69 | fmt.Println(strings.TrimSpace(panicOutput)) |
| 70 | } |
| 71 | } |
no test coverage detected
searching dependent graphs…