[macOS 26.901.51231] ReplyChannel prefinalization allocates during GC, tripping GCTracer ATOMIC check
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
macOS 26.901.51231: ReplyChannel error fallback allocates during GC and trips GCTracer's atomic-pause check
Version and platform
- ChatGPT desktop / Codex, bundle
com.openai.codex: 26.901.51231 (8109). - Codex Framework: 152.0.7977.83, ARM64, UUID
4c4c4409-5555-3144-a14d-e5a8bc58810f. - macOS 26.6.1 (25G76), Apple Silicon, 24 GB RAM.
- Bundled app-server:
codex-cli 0.153.4. - The installed app passed deep/strict code-signature verification with OpenAI's Developer ID.
- Subscription omitted from this sanitized native-runtime report.
- The production appcast still offered 8109 as its newest entry when checked at 2026-09-07 06:47 UTC.
Observed failure
The entire desktop app terminated during an active session. The macOS report records EXC_BREAKPOINT / SIGTRAP, signal 5, on thread 0 (CrBrowserMain, main queue). The process had been running for approximately five hours.
Timeline (UTC):
06:13:54.213: last desktop log event:IAB_LIFECYCLE ended browser use session activity,disposeAfterSessionActivity=false.06:13:54.413: macOS kernel logs the crashed process/core-dump denial.06:13:55.0895: Apple crash-report capture timestamp.06:33:58: app relaunched.
The browser-session event is timing context. It does not establish which IPC request was abandoned or why.
Native cause identified from the installed binary
The symbol labels in the Apple report are incomplete and often name unrelated exported functions with enormous offsets. I inspected the matching, unchanged framework offline, using image-relative addresses rather than treating those labels as function identities.
The recorded stack and machine code identify this sequence:
- A cppgc prefinalization callback runs with an outstanding
ReplyChannelcallback. - The callback moves its outstanding reply and directly calls the error fallback with the literal
reply was never sent. - That fallback calls
v8::Object::Newto construct an object containing anerrorproperty. - That object creation re-enters garbage collection while a collection is already in its atomic pause.
GCTracer::StartCyclerejects the reentrant cycle and executes the trap.
Selected exact evidence, all addresses relative to the framework image:
| Address | Evidence |
|---|---|
0x1ba5390 |
cppgc callback dispatch; next stack return address is 0x1ba5394 |
0x4677eb4 |
Loads literal reply was never sent |
0x4677ebc |
Direct bl 0x467822c; recorded return address 0x4677ec0 |
0x46782a4 |
Calls exported v8::Object::New; recorded return address 0x46782a8 |
0x46782bc |
Loads property name error |
0x1d98d30 |
Loads the current GC state into w8 |
0x1d98d44 |
Nonzero state branches to the state check |
0x1d98f88 |
Compares state with 3 |
0x1d98f8c |
Branches to 0x1d9912c when unequal |
0x1d9912c |
brk #0; exactly the crash PC after removing the image base |
The crash registers contain x8=2. The V8 revision pinned by Chromium 152.0.7977.83 is 4323497a6a73839e6d5260f6acd7ec0212cb3321. Its GC state enum maps 2 to ATOMIC and 3 to SWEEPING. Its StartCycle check matches the observed branch: a running cycle may be interrupted only while sweeping.
This establishes the failing GC invariant and strongly identifies unsafe reply finalization as the native cause. Full private-symbol symbolication would confirm the custom fork's exact function names and source locations.
Existing upstream protection to port and verify
Electron's lifetime refactor in PR #49339, merged January 15, 2026, commit ddeb970f18e6d228937ce1014e4b66624e2d447b, contains the relevant protection.
In Electron v42.3.0 ReplyChannel::EnsureReplySent, the fallback is posted to the current thread's task runner, carrying the moved callback, so V8 object allocation happens after GC. The source explicitly identifies GC-time V8 allocation as the reason for deferral. The installed custom framework instead makes the direct call shown above.
Please adopt the equivalent deferred-reply/lifetime fix in the Codex Framework branch, including its isolate-shutdown handling. The app's packaged JavaScript metadata names Electron 42.3.0, but that is not proof that the custom native framework contains the corresponding upstream fix.
Reproduction and validation status
This is an observed crash with a binary-level causal trace; no minimal deterministic live reproduction has been established. I did not force another crash of the active desktop app. The precise abandoned IPC channel is unavailable in the retained crash evidence.
Suggested native regression case: allow an unanswered invocation's reply wrapper to become unreachable, collect it under allocation pressure, and verify that its error reply is deferred until collection completes, sent at most once, and handled safely during isolate shutdown.
Resource and diagnostic context
- The last pre-crash resource sample,
06:11:57Z, showed 30 renderer processes, 7,102.4 MiB aggregate renderer RSS, 28.8% aggregate renderer CPU, and 50% in thememory_pressure -Qfree-percentage field. - This does not establish OS memory exhaustion. The observed termination was the explicit GC-state trap.
- An existing local resource guardian did not stop the app at this time. Its last completed recovery was approximately 5 hours 51 minutes earlier; it then deferred recovery during active work.
- A separate local telemetry reader was found selecting a stale local-date log instead of the current PID's UTC log. Its tab counts are excluded from the crash attribution.
- Raw logs, conversation text, account identifiers, browser state, and the complete Apple report are omitted from this public report.
Framework SHA-256: d6a0df29c859dd8ab37d81f602f548b4a17f004652997667f2b87e91cac3738c.
This report isolates the native reply-finalization/GC failure. Its relationship to browser-route multiplication in #42595 has not been established. Other main-process SIGTRAP reports exist, including #43089; I have not established whether those crashes share this cause.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Compare Electron v42.3.0's shell/common/gin_helper/reply_channel.cc and commit ddeb970f18e6d228937ce1014e4b66624e2d447b, then locate the equivalent ReplyChannel implementation in the Codex Framework. Validate the deferred reply under GC pressure, ensuring it sends at most once and remains safe during isolate shutdown.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, electron
- Domain
- desktop-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100