(main, failed chan *seccomp.Notif)
| 225 | } |
| 226 | |
| 227 | func (e *Engine) panicGuard(main, failed chan *seccomp.Notif) { |
| 228 | err := recover() |
| 229 | if err == nil { |
| 230 | return |
| 231 | } |
| 232 | |
| 233 | stack := debug.Stack() |
| 234 | e.inPanic.Store(true) |
| 235 | |
| 236 | b := new(bytes.Buffer) |
| 237 | fmt.Fprintf(b, "subtrace: engine panic: %v\n", err) |
| 238 | fmt.Fprintf(b, "\n") |
| 239 | fmt.Fprintf(b, "-----BEGIN SUBTRACE CRASH REPORT-----\n") |
| 240 | fmt.Fprintf(b, "time: %s\n", time.Now().Format(time.RFC3339Nano)) |
| 241 | fmt.Fprintf(b, "version: %s\n", version.Full(false)) |
| 242 | fmt.Fprintf(b, "panic: %+v\n", err) |
| 243 | fmt.Fprintf(b, "stack trace: %s\n", strings.TrimSpace(string(stack))) |
| 244 | fmt.Fprintf(b, "-----END SUBTRACE CRASH REPORT-----\n") |
| 245 | fmt.Fprintf(b, "\n") |
| 246 | fmt.Fprintf(b, "[CRITICAL] !!! Subtrace encountered a critical error. The tracing engine will\n") |
| 247 | fmt.Fprintf(b, "[CRITICAL] !!! now enter safe mode. New requests will no longer be traced.\n") |
| 248 | fmt.Fprintf(b, "[CRITICAL] !!! We're sorry about this. Please consider filing a bug report at\n") |
| 249 | fmt.Fprintf(b, "[CRITICAL] !!! https://github.com/subtrace/subtrace with the above crash report.\n") |
| 250 | fmt.Fprintf(b, "\n") |
| 251 | |
| 252 | // Write all the bytes at once so that there's as little interference between |
| 253 | // different processes writing to stderr at the same time. The tracer NEVER |
| 254 | // writes to stdout or stderr for this exact reason (unless it is started |
| 255 | // with -v or -log=true), but this is the exception to the rule. |
| 256 | os.Stderr.Write(b.Bytes()) |
| 257 | |
| 258 | go e.drainSafeMode(failed) |
| 259 | e.drainSafeMode(main) |
| 260 | } |
| 261 | |
| 262 | func (e *Engine) drainSafeMode(ch chan *seccomp.Notif) { |
| 263 | for n := range ch { |
no test coverage detected