github.com/hashicorp/packer@v1.14.3/panic.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package main
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"os"
    10  	"strings"
    11  
    12  	"github.com/hashicorp/packer/packer"
    13  	"github.com/mitchellh/panicwrap"
    14  )
    15  
    16  // This is output if a panic happens.
    17  const panicOutput = `
    18  
    19  !!!!!!!!!!!!!!!!!!!!!!!!!!! PACKER CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    20  
    21  Packer crashed! This is always indicative of a bug within Packer.
    22  A crash log has been placed at "crash.log" relative to your current
    23  working directory. It would be immensely helpful if you could please
    24  report the crash with Packer[1] so that we can fix this.
    25  
    26  [1]: https://github.com/hashicorp/packer/issues
    27  
    28  !!!!!!!!!!!!!!!!!!!!!!!!!!! PACKER CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    29  `
    30  
    31  // panicHandler is what is called by panicwrap when a panic is encountered
    32  // within Packer. It is guaranteed to run after the resulting process has
    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  }