aboutsummaryrefslogtreecommitdiffstats
path: root/log/panic-logger.go
diff options
context:
space:
mode:
Diffstat (limited to 'log/panic-logger.go')
-rw-r--r--log/panic-logger.go60
1 files changed, 60 insertions, 0 deletions
diff --git a/log/panic-logger.go b/log/panic-logger.go
new file mode 100644
index 00000000..a1904415
--- /dev/null
+++ b/log/panic-logger.go
@@ -0,0 +1,60 @@
+package log
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "runtime/debug"
+ "strings"
+ "time"
+)
+
+var (
+ UICleanup = func() {}
+ BuildInfo string
+)
+
+// PanicHandler tries to restore the terminal. A stack trace is written to
+// aerc-crash.log and then passed on if a panic occurs.
+func PanicHandler() {
+ r := recover()
+
+ if r == nil {
+ return
+ }
+
+ UICleanup()
+
+ filename := time.Now().Format("/tmp/aerc-crash-20060102-150405.log")
+
+ panicLog, err := os.OpenFile(filename, os.O_SYNC|os.O_APPEND|os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0o600)
+ if err != nil {
+ // we tried, not possible. bye
+ panic(r)
+ }
+ defer panicLog.Close()
+
+ outputs := io.MultiWriter(panicLog, os.Stderr)
+
+ // if any error happens here, we do not care.
+ fmt.Fprintln(panicLog, strings.Repeat("#", 80))
+ fmt.Fprint(panicLog, strings.Repeat(" ", 34))
+ fmt.Fprintln(panicLog, "PANIC CAUGHT!")
+ fmt.Fprint(panicLog, strings.Repeat(" ", 24))
+ fmt.Fprintln(panicLog, time.Now().Format("2006-01-02T15:04:05.000000-0700"))
+ fmt.Fprintln(panicLog, strings.Repeat("#", 80))
+ fmt.Fprintf(outputs, "%s\n", panicMessage)
+ fmt.Fprintf(outputs, "Version: %s\n", BuildInfo)
+ fmt.Fprintf(panicLog, "Error: %v\n\n", r)
+ panicLog.Write(debug.Stack()) //nolint:errcheck // we are already in a panic, so not much we can do here
+ fmt.Fprintf(os.Stderr, "\nThis error was also written to: %s\n", filename)
+ panic(r)
+}
+
+const panicMessage = `
+aerc has encountered a critical error and has terminated. Please help us fix
+this by sending this log and the steps to reproduce the crash to:
+~rjarry/aerc-devel@lists.sr.ht
+
+Thank you
+`