diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-03 13:29:50 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-03 13:29:50 -0300 |
| commit | e6c9f1726cca910c464fc807aefebc404c8e7a12 (patch) | |
| tree | 0bbcb79ae26a006afa40a4a8b26215a81610fb49 /src/modal.zig | |
| parent | 7c6165f184e45af30ac697f8e8a584529ac4a287 (diff) | |
| download | pardes-e6c9f1726cca910c464fc807aefebc404c8e7a12.tar.gz pardes-e6c9f1726cca910c464fc807aefebc404c8e7a12.zip | |
crash: a panic record must not be able to hang the process it is recording
Adversarial re-review, confirmed against std's source and then measured.
`captureCurrentStackTrace` is not the safe half of `writeCurrentStackTrace`.
`StackIterator.init` picks the `.di` strategy whenever `SelfInfo` can unwind,
`stratOk` accepts `.di` regardless of `allow_unsafe_unwind`, and `.di` takes
`SelfInfo`'s rwlock EXCLUSIVELY on its first call — the only kind of call a
panic record makes — across `dl_iterate_phdr`, a DWARF CFI machine and an
allocation. A panic in there (a smashed stack is a leading reason to be in a
panic handler at all) leaves the lock held, because the unlock is a `defer` in
a frame that never returns, and `defaultPanic` then waits on it for the life of
the process. A crash becomes a hang, which is worse than what this file was
added to improve on. The frames stay on stderr, where defaultPanic prints them
under the staging that makes them safe; the record keeps what can be gathered
without asking the process any questions.
ONE record per process, never released. With the guard released on the way out,
one panic wrote two records: the real message, then "reached unreachable code"
under it. That second panic is this handler's own `vaxis.recover()` running a
second time — it closes the vaxis tty and never clears the global saying there
is one, so the double close is `recoverableOsBugDetected` and an `unreachable`
in a Debug build. Guarded now in both the panic and the segfault handler; that
half is a fix older than the crash file.
`clock_gettime`'s return is checked, unlike dump.zig's, because a failure here
leaves `ts` undefined and an undefined large-positive `sec` walks
`calculateYearDay`'s u16 year past 65535 and overflow-panics inside the panic
handler. Debug fills it with 0xaa and lands in 1970, which is why it reads as
harmless.
Verified end to end with a temporary probe: one panic, one record.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016Q4RATpafkwahrovHQLKRf
Diffstat (limited to 'src/modal.zig')
0 files changed, 0 insertions, 0 deletions
