Publish harness and TUI open-source
initial sync from the monorepo
This commit is contained in:
commit
c68e39f604
2734 changed files with 1437016 additions and 0 deletions
47
crates/codegen/xai-crash-handler/README.md
Normal file
47
crates/codegen/xai-crash-handler/README.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# xai-crash-handler
|
||||
|
||||
Crash handler for SIGBUS/SIGSEGV with best-effort backtrace capture.
|
||||
|
||||
## How it works
|
||||
|
||||
`install()` registers a `sigaction` handler. On crash it writes a binary blob (`GCRX` format) to `crash_dir/last-crash.bin` and restores the terminal via pre-computed escape sequences. The handler uses only async-signal-safe operations for file I/O, terminal restore, and re-raise.
|
||||
|
||||
On next launch, `check_previous_crash()` reads the blob, resolves IPs to symbols via `backtrace`, writes `last-crash-report.txt`, and archives it (keeping the last 5 reports).
|
||||
|
||||
No-ops on non-unix platforms. On musl-based Linux (release builds), the handler still records signal/address/version but skips frame capture since musl does not provide `backtrace()`.
|
||||
|
||||
## Limitations
|
||||
|
||||
### Frame capture is best-effort
|
||||
|
||||
Frame capture uses two fully async-signal-safe techniques:
|
||||
1. The crash instruction pointer is extracted directly from the `ucontext_t` passed by the kernel.
|
||||
2. Additional frames are captured by walking the frame-pointer chain (RBP on x86_64, x29 on aarch64) with raw pointer reads.
|
||||
|
||||
In release builds without `-C force-frame-pointers`, the frame-pointer chain may be incomplete or empty (the compiler omits frame pointers by default for optimization). The crash PC is always captured. In debug/dev builds, frame pointers are retained by default, producing fuller call stacks.
|
||||
|
||||
### sigaltstack is per-thread
|
||||
|
||||
The alternate signal stack is installed only on the thread that calls `install()`. Tokio worker threads do not inherit it. Stack overflows on worker threads will still trigger the handler (sigaction is process-wide), but without altstack protection the handler itself may fault on the overflowed stack.
|
||||
|
||||
## Usage
|
||||
|
||||
```rust
|
||||
use std::path::PathBuf;
|
||||
|
||||
let crash_dir = PathBuf::from("/home/user/.myapp/crash");
|
||||
|
||||
// check_previous_crash MUST be called before install(), because
|
||||
// install() opens last-crash.bin with O_TRUNC.
|
||||
if let Some(r) = xai_crash_handler::check_previous_crash(&crash_dir) {
|
||||
eprintln!("Crashed last session: {}", r.signal_name);
|
||||
eprintln!("Report: {}", r.report_path.display());
|
||||
}
|
||||
|
||||
// install() before any threads or async runtime — sigaltstack is per-thread.
|
||||
// Creates crash_dir if it does not exist.
|
||||
xai_crash_handler::install(xai_crash_handler::CrashHandlerConfig {
|
||||
app_version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
crash_dir,
|
||||
});
|
||||
```
|
||||
Loading…
Reference in a new issue