fix: prevent EXC_BREAKPOINT crash from V8 string allocation in stream…#7509
Closed
AE-33 wants to merge 1 commit intoblock:mainfrom
Closed
fix: prevent EXC_BREAKPOINT crash from V8 string allocation in stream…#7509AE-33 wants to merge 1 commit intoblock:mainfrom
AE-33 wants to merge 1 commit intoblock:mainfrom
Conversation
c9b4106 to
802810b
Compare
Contributor
Author
zanesq
pushed a commit
that referenced
this pull request
Feb 25, 2026
…n in check-ollama Adapted from PR #7509 — eliminates per-chunk Buffer.toString() calls in stream data handlers that contribute to V8 heap pressure in long sessions. - read-file: use fs.readFile() on all platforms instead of spawning cat - check-ollama: accumulate chunks, convert to string on stream close
… handlers
The Goose desktop app crashes with EXC_BREAKPOINT (SIGTRAP) / brk #0 on the
main thread (CrBrowserMain) approximately 29 minutes after launch.
Root cause: calling Buffer.toString() inside Node.js stream 'data' event
handlers on the Electron main thread triggers the following V8 code path:
Buffer.toString('utf8')
→ node::StringBytes::Encode()
→ v8::String::NewFromUtf8()
→ V8 NEW_STRING macro → .ToHandleChecked()
When V8 cannot allocate a new string (GC pressure, near-OOM, or isolate
state during concurrent garbage collection), NewFromUtf8 returns an empty
MaybeLocal, and ToHandleChecked() hits a CHECK → FATAL → brk #0 →
EXC_BREAKPOINT (SIGTRAP).
This is triggered because libuv delivers stream data chunks via callbacks
on the main thread's event loop. Each data.toString() call forces an
immediate V8 heap allocation in the hot I/O path, competing with GC.
Fixes applied to three vulnerable code paths:
1. check-ollama handler (main.ts): Accumulate raw Buffer chunks in arrays
during 'data' events, defer Buffer.concat().toString() to the 'close'
handler after the stream has ended.
2. read-file handler (main.ts): Replace spawn('cat') + stream piping with
fs.readFile() on all platforms. This returns a single Buffer after the
read completes, avoiding per-chunk V8 string allocation entirely.
3. goosed process stdout/stderr (goosed.ts): Batch raw Buffer chunks and
flush via setImmediate(), moving the toString() call out of the libuv
I/O callback and into a subsequent event loop tick where V8 heap
allocation is safer.
Crash signature from macOS crash report:
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000112b6cef0
Thread 0 Crashed: CrBrowserMain
0 Electron Framework ares_dns_rr_get_ttl + 3711128
...
29 node::StringBytes::Encode + 272
30 node::Buffer::RegisterExternalReferences + 25908
Electron 40.4.0 / Node.js 24.x / V8 14.4.x / macOS ARM64
Signed-off-by: Jacob Szymik <[email protected]>
802810b to
61cdf01
Compare
Contributor
Contributor
|
@AE-33 nvm it was a different contributor, cleaning that up in the branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes EXC_BREAKPOINT (SIGTRAP) crash on macOS ARM64 that occurs ~29 minutes after launch.
Root cause:
Buffer.toString()called inside Node.js stream'data'event handlers on the Electron main thread triggersnode::StringBytes::Encode()→v8::String::NewFromUtf8()→ V8CHECKassertion failure (brk #0) when V8 cannot allocate under GC pressure.Fixes applied to 3 vulnerable code paths:
setImmediate()— movestoString()out of the libuv I/O callback into the next event loop tickBuffer[]during'data'events, convert to string on'close'after stream endsspawn('cat')+ stream piping withfs.readFile()on all platforms — eliminates per-chunk V8 string allocation entirelyType of Change
AI Assistance
Testing
read-filehandler returns identical API shape (backward compatible)check-ollamahandler returns identical results (just defers string conversion)goosed.tslogging output is identical (just batched per event loop tick)Related Issues
Closes #7507