recoverFromGoPanic recovers from a goroutine panic, prints a stack trace and signals for the program to be killed and terminal restored to a usable state.
(r interface{})
| 1292 | // recoverFromGoPanic recovers from a goroutine panic, prints a stack trace and |
| 1293 | // signals for the program to be killed and terminal restored to a usable state. |
| 1294 | func (p *Program) recoverFromGoPanic(r interface{}) { |
| 1295 | select { |
| 1296 | case p.errs <- ErrProgramPanic: |
| 1297 | default: |
| 1298 | } |
| 1299 | p.cancel() |
| 1300 | // We use "\r\n" to ensure the output is formatted even when restoring the |
| 1301 | // terminal does not work or when raw mode is still active. |
| 1302 | rec := strings.ReplaceAll(fmt.Sprintf("%s", r), "\n", "\r\n") |
| 1303 | fmt.Fprintf(os.Stderr, "Caught panic:\r\n\r\n%s\r\n\r\nRestoring terminal...\r\n\r\n", rec) |
| 1304 | stack := strings.ReplaceAll(fmt.Sprintf("%s\n", debug.Stack()), "\n", "\r\n") |
| 1305 | fmt.Fprint(os.Stderr, stack) |
| 1306 | if v, err := strconv.ParseBool(os.Getenv("TEA_DEBUG")); err == nil && v { |
| 1307 | f, err := os.Create(fmt.Sprintf("bubbletea-panic-%d.log", time.Now().Unix())) |
| 1308 | if err == nil { |
| 1309 | defer f.Close() //nolint:errcheck |
| 1310 | fmt.Fprintln(f, rec) //nolint:errcheck |
| 1311 | fmt.Fprintln(f) //nolint:errcheck |
| 1312 | fmt.Fprintln(f, stack) //nolint:errcheck |
| 1313 | } |
| 1314 | } |
| 1315 | } |
| 1316 | |
| 1317 | // ReleaseTerminal restores the original terminal state and cancels the input |
| 1318 | // reader. You can return control to the Program with RestoreTerminal. |
no test coverage detected