|
1 | 1 | ## Codebase Patterns |
2 | | -- V8 SIGSEGV on v134.5.0 during Pi interactive TUI init is a confirmed blocker — not a stack overflow, not a bridge issue, crash is inside V8 JIT/C++ code after ~1600 modules loaded |
| 2 | +- V8 SIGSEGV on v134.5.0 during Pi interactive TUI init was caused by native Intl.Segmenter (ICU JSSegments::Create) — fixed with JS polyfill in bridge setupGlobals() and inline in test code for snapshot contexts |
| 3 | +- To debug V8 SIGSEGV: add SIGSEGV handler with backtrace_symbols_fd, write to file (SECURE_EXEC_V8_DIAG_FILE), then use addr2line on crash addresses to identify the specific V8 built-in |
| 4 | +- Intl.Segmenter polyfill must be applied BOTH in bridge setupGlobals() (fresh isolates) AND in user code (snapshot-restored contexts) until snapshot rebuild |
3 | 5 | - process.nextTick, queueMicrotask, and setTimeout(fn, 0) all route through _scheduleTimer bridge call (not V8 microtasks) — prevents perform_microtask_checkpoint() infinite loops |
4 | 6 | - Kernel VFS canonical source is now packages/secure-exec-core/src/kernel/vfs.ts — includes realpath, pread, full VirtualStat (ino, nlink, uid, gid) |
5 | 7 | - @secure-exec/kernel package has been deleted — all kernel types/functions import from @secure-exec/core directly |
@@ -1078,3 +1080,38 @@ Started: Sat Mar 21 02:49:43 AM PDT 2026 |
1078 | 1080 | - V8 sidecar "IPC connection closed" error flows: session.execute() rejects → executeInternal() catch → returns { code: 1, errorMessage } → kernel-runtime resolves (not rejects) |
1079 | 1081 | - To debug V8 SIGSEGV: need to run binary under GDB or with ASAN (release builds strip symbols, backtrace_symbols_fd returns unhelpful addresses) |
1080 | 1082 | --- |
| 1083 | + |
| 1084 | +## 2026-03-22 - US-028 (SIGSEGV root cause found and fixed) |
| 1085 | +- **Root cause identified**: V8's native `Intl.Segmenter` (ICU `JSSegments::Create`) crashes with SIGSEGV during `perform_microtask_checkpoint()`. Pi's TUI framework (Ink/cli-truncate) calls `Intl.Segmenter.prototype.segment()` for text wrapping. The crash happens in V8's C++ ICU code, not in Rust or JS bridge code. |
| 1086 | +- **Diagnosis method**: Custom SIGSEGV handler with `backtrace_symbols_fd` + `addr2line` on the crash address → identified `v8::internal::JSSegments::Create` and `Builtin_SegmenterPrototypeSegment` |
| 1087 | +- **Fix**: Added JS polyfill for `Intl.Segmenter` in bridge `setupGlobals()` (covers grapheme/word/sentence granularity). Also added inline polyfill in test code for snapshot-restored contexts. |
| 1088 | +- **Additional V8 improvements**: |
| 1089 | + - Preserve MODULE_RESOLVE_STATE module cache across event loop (execute_module no longer clears on success) |
| 1090 | + - Added `update_bridge_ctx()` to update bridge pointer without losing cached modules |
| 1091 | + - Set V8 `--stack-size=16384` for deep microtask chains |
| 1092 | + - Support `SECURE_EXEC_V8_JITLESS=1` env var for debugging |
| 1093 | + - Keep auto microtask policy during event loop (explicit policy starved the event loop) |
| 1094 | +- **Test results**: 4/9 Pi interactive tests pass (TUI renders, input, Ctrl+C, PTY resize). 5 fail on LLM streaming response and clean exit (separate issues from SIGSEGV). |
| 1095 | +- **What was NOT the cause** (investigated and ruled out): |
| 1096 | + - NOT TryCatch scope invalidation (Rust borrow checker prevents this) |
| 1097 | + - NOT HandleScope management in event loop |
| 1098 | + - NOT module cache loss (preserving cache didn't fix crash) |
| 1099 | + - NOT V8 version (136.0.0 same crash as 134.5.0) |
| 1100 | + - NOT JIT compilation bug (--jitless same crash) |
| 1101 | + - NOT stack overflow (128 MiB stack same crash) |
| 1102 | + - NOT snapshot corruption (no-snapshot same crash) |
| 1103 | + - NOT GC heap corruption (pre-event-loop GC didn't help) |
| 1104 | +- Files changed: |
| 1105 | + - native/v8-runtime/src/execution.rs (update_bridge_ctx, preserve module cache on success) |
| 1106 | + - native/v8-runtime/src/isolate.rs (--stack-size=16384, --jitless support) |
| 1107 | + - native/v8-runtime/src/session.rs (module cache preservation, auto microtask policy comment) |
| 1108 | + - native/v8-runtime/src/main.rs (cleanup diagnostic code) |
| 1109 | + - packages/nodejs/src/bridge/process.ts (Intl.Segmenter polyfill in setupGlobals) |
| 1110 | + - packages/secure-exec/tests/cli-tools/pi-interactive.test.ts (inline Segmenter polyfill) |
| 1111 | +- **Learnings for future iterations:** |
| 1112 | + - V8's native Intl.Segmenter (ICU) crashes on large module graphs — polyfill it in the bridge |
| 1113 | + - SIGSEGV during perform_microtask_checkpoint() can be caused by ANY V8 built-in called from microtask callbacks — use SIGSEGV handler + addr2line to identify the specific built-in |
| 1114 | + - V8 process stderr is NOT captured by vitest — use file-based logging (SECURE_EXEC_V8_DIAG_FILE) for crash diagnostics |
| 1115 | + - Explicit microtask policy starves the V8 event loop (timer callbacks don't chain properly) — keep auto policy |
| 1116 | + - The bridge's Intl.Segmenter polyfill only covers fresh isolates; snapshot-restored contexts need the polyfill re-applied in user code or postRestoreScript |
| 1117 | +--- |
0 commit comments