[app][macOS][26.810.52044] Unbounded SkyComputerUseService respawn loop crashes the app in ~2 min — onServiceConnectionLost has no failure counter, backoff, or circuit breaker

Open 💬 4 comments Opened Aug 16, 2026 by aresxu8866-hue
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

[app][macOS][26.810.52044] Unbounded SkyComputerUseService respawn loop crashes the app in ~2 min — onServiceConnectionLost has no failure counter, backoff, or circuit breaker

Summary

On macOS, the ChatGPT/Codex desktop app enters an unbounded respawn loop for the Computer Use PiP helper (SkyComputerUseService) whenever the PiP bootstrap handshake fails. Each iteration leaks a live 75 MB helper process and permanently blocks a main-app thread, so the app reaches the V8 heap limit and aborts roughly 2 minutes after launch — with no user interaction and without Computer Use ever being invoked.

The native (ObjC/C++) side of the handshake is implemented correctly: it has a 15 s Apple Event timeout, a 5-attempt cap, and exponential backoff. The defect is in the JavaScript layer above it, where the connection-lost callback is a no-op that only nulls the cached PID. I have traced this to a specific callback in app.asar and include a proposed patch below.

This appears to be the same underlying defect behind several existing reports (see [Related](#related-issues)); this issue adds the root cause and a specific code location.

---

Environment

| | |
|---|---|
| App | ChatGPT.app 26.810.52044 (build 6662), bundle id com.openai.codex |
| Framework | Codex Framework 151.0.7922.137 |
| macOS | 26.3 (25D125) |
| Hardware | Mac16,10 (Mac mini, Apple Silicon), 16 GB RAM |
| Computer Use helper | 26.812.1000717, at ~/.codex/computer-use/Codex Computer Use.app |
| Install source | https://persistent.oaistatic.com/codex-app-prod/ChatGPT.dmg (verified: the downloaded DMG is byte-identical in version/build to the installed app) |

Reported crashing builds in the community thread: 6570, 6644, 6662.

---

Reproduction

  1. Launch ChatGPT.app.
  2. Do nothing. Do not open a project, do not use Computer Use, do not interact at all.
  3. The app aborts after ~70–150 s.

100% reproducible on this machine across 5+ consecutive launches.

---

Observed behaviour

Helper process explosion

SkyComputerUseService instances, all children of the main app process, none reaped:

| Time since launch | Live helper processes | Combined RSS |
|---|---|---|
| 12 s | 36 | ~2.7 GB |
| 25 s | 79 | ~5.9 GB |
| 30 s | 105 | ~7.9 GB |
| ~40 s (manually killed) | 199 | 12.5 GB |

Spawn rate ≈ 5/s. Each helper is ~75 MB and stays alive and healthy — sampling one shows a normal, idle NSApplicationMain run loop parked in mach_msg2_trap. They are never asked to exit and never reaped.

Main-process thread exhaustion

| Time since launch | Threads in main process |
|---|---|
| 5 s | 2 |
| 60 s | 209 |
| 120 s | 309 → crash |

Growth is linear and monotonic; threads are never released.

Crash report

Exception Type:  EXC_CRASH (SIGABRT)
Termination Reason: Namespace SIGNAL, Code 6, Abort trap: 6
Dispatch Thread Soft Limit Reached: 64 (too many dispatch threads blocked in synchronous operations)
Triggered by Thread: 9  V8Worker

Thread 9 Crashed:
0  libsystem_kernel.dylib  __pthread_kill
1  libsystem_pthread.dylib pthread_kill
2  libsystem_c.dylib       abort
3  Codex Framework         node::OOMErrorHandler(char const*, v8::OOMDetails const&)

Thread-name histogram at crash time (321 threads total):

187  computer-use
 64  com.apple.root.user-initiated-qos
 16  ThreadPoolForegroundWorker
  ...

Every one of the 187 computer-use threads is parked identically:

libsystem_kernel.dylib  __ulock_wait
libdispatch.dylib       _dlock_wait
libdispatch.dylib       _dispatch_group_wait_slow
AE                      AESendMessage
node.napi.armv8.node    ffi_call_SYSV
sky.node                Napi::details::CallbackData<...>::Wrapper
Codex Framework         napi_is_detached_arraybuffer

and the 64 QoS threads (which is exactly the dispatch soft limit) are parked in:

AE                      AESendMessage
Foundation              -[NSAppleEventDescriptor sendEventWithOptions:timeout:error:]
sky.node                -[RemoteHostedPIPContentService sendBootstrapToServiceWithProcessIdentifier:rendezvousPort:attempt:]

Log evidence

log stream --predicate 'process == "ChatGPT"' during startup:

sky.node  RemoteHostedPIPContent started private endpoint host
xpc       [0x...] failed to do a bootstrap look-up: xpc_error=[3: No such process]
appleevents  AESendMessage(SkCu,PiPB {SkCu,PiPB target='kpid'[pid=32651  returnID=24465}...
appleevents  AESendMessage(SkCu,PiPB {SkCu,PiPB target='kpid'[pid=32700  returnID=-4047}...
appleevents  AESendMessage(SkCu,PiPB {SkCu,PiPB target='kpid'[pid=32705  returnID=22616}...
appleevents  AESendMessage(SkCu,PiPB {SkCu,PiPB target='kpid'[pid=32709  returnID=...}...

The target PID differs on every send — confirming a fresh helper is spawned per attempt rather than the existing one being reused.

---

Root cause

The native retry logic is correct

Disassembly of -[RemoteHostedPIPContentService sendBootstrapToServiceWithProcessIdentifier:rendezvousPort:attempt:] in Contents/Resources/native/sky.node (symbols are not stripped; function at 0xd474):

Event constructioneventClass = 'SkCu', eventID = 'PiPB':

d504  mov   w2, #0x4375
d508  movk  w2, #0x536b, lsl #16        ; 'SkCu'
d50c  mov   w3, #0x5042
d510  movk  w3, #0x5069, lsl #16        ; 'PiPB'
d520  bl    appleEventWithEventClass:eventID:targetDescriptor:returnID:transactionID:

Send with a bounded 15 s timeout (options = 0x23 = kAEWaitReply | kAECanInteract):

d5d4  fmov  d0, #15.00000000            ; timeout = 15 s
d5e0  mov   w2, #0x23                   ; kAEWaitReply | kAECanInteract
d5e4  bl    sendEventWithOptions:timeout:error:

Attempt cap of 5 (attempt arrives in x4, spilled to [sp,#0x10]):

d494  str   x4, [sp, #0x10]             ; save attempt
...
d73c  ldr   x10, [sp, #0x10]
d740  sub   x8, x10, #0x5
d744  cmn   x8, #0x7
d748  b.hi  0xd7b4                      ; attempt in 0..4 -> retry; attempt >= 5 -> give up

Exponential backoff, 50 ms << attempt (0xF4240 = 1e6 ns/ms):

d7b4  mov   w8, #0x32                   ; 50
d7b8  lsl   x8, x8, x10                 ; 50 << attempt
d7bc  mov   w9, #0x4240
d7c0  movk  w9, #0xf, lsl #16           ; 1_000_000
d7c4  mul   x1, x8, x9                  ; -> nanoseconds
d7d0  bl    dispatch_time
d7e0  bl    dispatch_get_global_queue

So the native layer retries at 50/100/200/400/800 ms (5 attempts, ~1.55 s total) and then correctly gives up, logging and dispatching the failure callback to the main queue.

The JavaScript layer discards that failure

From Contents/Resources/app.asar (minified; identifiers are the shipped mangled names):

te = () => {
  if (!(D || v || !n || !t()) && (
    oe(),
    v = ko({
      controlTooltips: c(),
      onServiceConnectionLost: () => { b = null }     // <-- the entire failure handler
    }),
    v
  )) {
    b != null && Ao(b), se(), B(), ce(), le(), me()
    for (let e of _) e()
  }
}

where ko(...)startRemoteHostedPIPContentHost(tooltips, onServiceConnectionLost), Ao(pid)connectRemoteHostedPIPContentHost(pid), and the spawn path is:

async function Eo(path, { addon: t, electronAppPath: n, platform: r, resourcesPath: i } = {}) {
  return r !== `darwin` || path.trim() === ``
    ? null
    : (t ?? so({ electronAppPath: n, resourcesPath: i })).spawnComputerUseService(path)
}

onServiceConnectionLost only nulls the cached PID. There is no failure counter, no delay, no ceiling, and no disable path. Once b is null, the next invocation of te() — triggered by ordinary UI/state changes — spawns another helper immediately, and the previously spawned helper is never terminated.

Searching the entire 267 MB app.asar for any restart-throttling mechanism:

| identifier | occurrences |
|---|---|
| maxRestart | 0 |
| restartCount | 0 |
| consecutiveFailure | 0 |
| circuitBreak | 0 |

No global restart circuit breaker exists.

Why the handshake fails in the first place

Not fully determined. The XPC bootstrap look-up fails with [3: No such process] immediately before the app falls back to the Apple Event path, and the spawned helper — while alive and idle in a normal run loop — never answers SkCu/PiPB.

Note that com.openai.codex has Apple Events authorization entries for com.apple.Terminal, com.apple.finder, com.apple.systemevents, com.google.Chrome and others, but no entry targeting com.openai.sky.CUAService, while other clients on this machine (python, node, other apps) do have that pairing. tccd logs during startup show no AppleEvents authorization request for that target, so this is an observation rather than a confirmed cause.

Regardless of why the handshake fails, the unbounded respawn is an independent defect and is what turns a recoverable failure into a crash.

---

Proposed fix

Give onServiceConnectionLost a failure counter, backoff, and circuit breaker, and reap the previous helper before spawning a new one:

let cuFailCount = 0
let cuDisabled = false

onServiceConnectionLost: () => {
  b = null
  if (cuDisabled) return
  if (++cuFailCount >= 3) {
    cuDisabled = true                                  // stop trying; surface a UI notice
    log.warn('Computer Use host unavailable; disabling for this session')
    return
  }
  setTimeout(te, Math.min(1000 * 2 ** cuFailCount, 30_000))
}

and reset cuFailCount = 0 on a successful connect.

Additionally:

  1. Terminate the previous helper before spawning a replacement. spawnComputerUseService should either reuse a live helper (computerUseServiceProcessMatchesExecutablePath already exists for this check) or kill the stale one. Today, helpers accumulate without bound and are never reaped — this is also the substance of #25744 and the zombie-process reports.
  2. Bound in-flight bootstraps. With a 15 s Apple Event timeout and a ~200 ms spawn cadence, up to ~75 bootstraps can be in flight simultaneously, each holding a blocked thread. The 64-thread dispatch soft limit is hit well before any of them time out.
  3. Do not run the bootstrap on com.apple.root.user-initiated-qos. Synchronously blocking global-queue threads on AESendMessage is what exhausts the dispatch pool.

---

Workaround (verified)

Making the helper bundle non-executable stops the loop entirely:

chmod 000 "$HOME/.codex/computer-use/Codex Computer Use.app"

Result — measured over a continuous 14.5 h run:

| | before | after |
|---|---|---|
| Helper processes | 199 and climbing | 0 |
| Main-process threads | 309 @ 2 min | 63, flat |
| App memory | 12.5 GB and climbing | 347 MB, flat |
| Stability | crash @ ~2 min | no crash in 14.5 h |

Computer Use is unavailable, but every other feature works normally. Reverse with chmod 755 on the same path.

Deleting or renaming the helper bundle does not work — the app re-provisions an identical copy on next launch.

---

Possibly related: idle renderer memory growth

Likely a separate defect, noted here because it appears in the same reports. On a clean launch with nothing opened, the app starts 7 renderers. Four of them (renderer-client-id 7–10, created within 36 ms of each other and identical in size) grow steadily while completely idle:

| renderer | at launch | after 14.5 h | growth |
|---|---|---|---|
| #5 (main UI) | 304 MB | 346 MB | +14% |
| #6 | 182 MB | 263 MB | +45% |
| #7 | 102 MB | 1428 MB | +1300% |
| #8 | 101 MB | 1426 MB | +1300% |
| #9 | 102 MB | 1425 MB | +1300% |
| #10 | 100 MB | 1424 MB | +1300% |

Measured rate ≈ 320 MB/h per renderer (16 MB per 3 min, sampled). Growth is in app-specific tag 14 (JS heap): 1145 MB → 1373 MB, with region count rising 4385 → 4754.

Notably these four processes accumulated only 2.5–9.3 seconds of CPU time over 14.5 hours, so whatever is allocating is doing almost no work. Total app footprint reached 7.67 GB; a restart brings it back to 1.45 GB. On a 16 GB machine this drove swap to 7.74 GB of 8 GB.

The renderers that are actually in use are fine — the leak is in the four idle pre-warmed ones.

---

Related issues

---

Contact

Happy to provide the full .ips crash reports, log stream captures, disassembly, or to run any additional diagnostics on request — just ask here.

---

Notes on this machine's configuration

For completeness: this machine uses a customized ~/.codex/config.toml (custom openai_base_url pointing at a local router, custom model catalog, sandbox_mode = "danger-full-access", 6 MCP servers), and ~/.codex is a symlink to an external volume. The failure path above is entirely within the Computer Use PiP bootstrap and is independent of model routing; the identical crash signature has been reported by users on stock configurations.

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 12 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #38813
  • #38771
  • #38769
  • #38744
  • #38515

Powered by Codex Action

yspreen · 11 days ago

this actually crashes my mac not just chatgpt. no other app open, one prompt, 2min later mac freezes then screen goes black. only holding power button resolves it, no input is registered. I downgraded to 26.803.61601 that fixes it. writeup https://spreen.co/codex-macos-crash-transcript/

FYuei · 5 days ago

Follow-up: still reproducible on builds 6849 and 6962, with 16 crash reports

I have a longitudinal evidence set for the same unbounded Computer Use respawn/thread-exhaustion failure described here. The important new information is that the issue continued after build 6662 in two later app builds and two later Computer Use runtimes.

Environment and affected versions

  • Hardware: Apple Silicon Mac (Mac17,3), 10 logical CPUs, 16 GB RAM
  • OS: macOS 26.4.1 (25E253)
  • Bundle ID: com.openai.codex
  • Affected app/runtime pairs observed:
  • ChatGPT 26.810.52044 (build 6662) / Computer Use 26.812.1000717
  • ChatGPT 26.818.21641 (build 6849) / Computer Use 26.818.1000790
  • ChatGPT 26.818.41509 (build 6962) / Computer Use 26.819.1000816

Crash-report evidence

There are 16 original macOS .ips reports from Aug 15-23, 2026:

  • 13 reports from build 6662
  • 1 report from build 6849
  • 2 reports from build 6962
  • Every report has 316-324 main-process threads at failure.
  • Every faulting thread is named either computer-use or V8Worker (9 computer-use, 7 V8Worker).
  • 13 failures are EXC_CRASH / SIGABRT; their faulting stacks contain node::OOMErrorHandler(...) -> abort().
  • 3 failures are EXC_BREAKPOINT / SIGTRAP, also on a computer-use worker path.
  • Each report records Dispatch Thread Soft Limit: 64.
  • A representative report contains 187 threads named computer-use and exactly 64 com.apple.root.user-initiated-qos threads. The latter are blocked in AESendMessage -> -[NSAppleEventDescriptor sendEventWithOptions:timeout:error:] -> -[RemoteHostedPIPContentService sendBootstrapToServiceWithProcessIdentifier:rendezvousPort:attempt:].

The two build 6962 crashes occurred 2m03s and 1m54s after launch. This is the same timing and crash shape as build 6662, not a separate generic Electron OOM.

Process and system impact observed

  • Live SkyComputerUseService count reached 458 on build 6662 and 547 on build 6849.
  • At one sampled point, 401 service processes had the same PPID as the sole ChatGPT main process.
  • Spawn cadence was approximately 5 new helpers per second.
  • Peak load average reached 194.56 on build 6662 and 450.49 on build 6849 on a 10-logical-CPU system.
  • Quitting ChatGPT caused the helper population to disappear and load to return toward baseline.
  • The services created hundreds of PreventUserIdleSystemSleep assertions, so the incident also prevented normal sleep and caused severe battery/thermal impact.

Reproduction and mitigation observations

  • The failure occurs after launching the app without invoking Computer Use.
  • Rebooting and a clean reinstall of the same affected build did not prevent recurrence.
  • Removing the Computer Use payload was not durable: the app downloaded a fresh ~65 MB copy within 47 seconds.
  • Preventing the payload from being reinstalled stopped the process/thread explosion.
  • A local control run using app build 6234 with Computer Use 26.803.1000621 remained stable, while later runtimes 1000717, 1000790, and 1000816 reproduced the issue.

Interpretation

The crash reports directly confirm main-process Computer Use worker accumulation, dispatch-pool exhaustion, and V8 OOM/abort. The live process samples independently confirm an unbounded SkyComputerUseService population owned by ChatGPT. Together these observations support the root cause described in this issue: a failed bootstrap is converted into an unbounded respawn loop without a global in-flight limit, backoff/circuit breaker at the caller, or cleanup of prior helpers.

The initial reason the bootstrap handshake fails on this machine is still not established. That should remain separate from the confirmed containment defect: one failed handshake must not be able to create hundreds of processes/threads, prevent sleep, overload the machine, and crash the app.

Requested follow-up

  1. Please confirm whether a fix is planned or already landed for builds after 6962 / Computer Use 1000816.
  2. Add a strict global cap on in-flight bootstraps and live Computer Use helpers.
  3. Terminate/reap the previous helper before replacement and add exponential backoff plus a session circuit breaker.
  4. After repeated startup crashes, relaunch in a safe mode with Computer Use disabled.
  5. Ensure disabling Computer Use prevents startup registration, notification hooks, and silent payload reinstallation.

I can provide the 16 original .ips reports privately. I am not attaching them publicly because they contain local device and diagnostic identifiers.

MariusVatasoiu · 3 days ago

I also have this issue. After 2 minutes the app crashes.

-------------------------------------
Translated Report (Full Report Below)
-------------------------------------
Process:             ChatGPT [43224]
Path:                /Applications/ChatGPT.app/Contents/MacOS/ChatGPT
Identifier:          com.openai.codex
Version:             26.818.61809 (7019)
Code Type:           ARM-64 (Native)
Role:                Background
Parent Process:      launchd [1]
Coalition:           com.openai.codex [14192]
User ID:             501

Date/Time:           2026-08-24 22:57:56.2317 +0300
Launch Time:         2026-08-24 22:55:01.7526 +0300
Hardware Model:      Mac14,9
OS Version:          macOS 26.6.2 (25G83)
Release Type:        User

Crash Reporter Key:  4BBAA5A1-747D-82B6-EF0D-FBF960C55990
Incident Identifier: 7562A13A-3BD9-4CB4-A963-0D131ADB4F46

Sleep/Wake UUID:       99EBCCF1-2336-4FCE-B3CF-731E801A94EF

Time Awake Since Boot: 59000 seconds
Time Since Wake:       1413 seconds

System Integrity Protection: enabled

Triggered by Thread: 11  V8Worker

Exception Type:    EXC_CRASH (SIGABRT)
Exception Codes:   0x0000000000000000, 0x0000000000000000

Termination Reason:  Namespace SIGNAL, Code 6, Abort trap: 6
Terminating Process: ChatGPT [43224]


Dispatch Thread Soft Limit Reached: 64 (too many dispatch threads blocked in synchronous operations)

Application Specific Information:
abort() called


Thread 0:: CrBrowserMain Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	       0x184067c34 mach_msg2_trap + 8
1   libsystem_kernel.dylib        	       0x18407a5a4 mach_msg2_internal + 76
2   libsystem_kernel.dylib        	       0x1840709c0 mach_msg_overwrite + 480
3   libsystem_kernel.dylib        	       0x184067fc0 mach_msg + 24
4   SkyLight                      	       0x18aa20680 SLSCopyRegisteredCursorImages + 376
5   AppKit                        	       0x188e5d2a4 +[NSCursor(NSDeprecated) currentSystemCursor] + 88
6   Codex Framework               	       0x11bb5ebbc _v8_internal_Node_Print(void*) + 10720760
7   CoreFoundation                	       0x184149664 __invoking___ + 148
8   CoreFoundation                	       0x1841494f0 -[NSInvocation invoke] + 424
9   CoreFoundation                	       0x18417da00 -[NSInvocation invokeWithTarget:] + 64
10  Codex Framework               	       0x11dd21040 node::inspector::protocol::BinaryValue::asBinary(node::inspector::protocol::Binary*) const + 21574952
11  CoreFoundation                	       0x184147da8 ___forwarding___ + 1032
12  CoreFoundation                	       0x1841478e0 _CF_forwarding_prep_0 + 96
13  AppKit                        	       0x1887a9cec -[NSTrackingArea mouseMoved:] + 116
14  AppKit                        	       0x18903aff0 -[_NSTrackingAreaAKManager _mouseMoved:] + 448
15  AppKit                        	       0x18936879c _routeMouseMovedEvent + 240
16  AppKit                        	       0x1886c2264 -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 556
17  AppKit                        	       0x1886c1e94 -[NSWindow(NSEventRouting) sendEvent:] + 380
18  Codex Framework               	       0x11990a9bc uv_os_getpid + 88448
19  Codex Framework               	       0x1190ea638 uv_req_get_type + 521000
20  AppKit                        	       0x189132d68 routeMouseMovedEvent + 148
21  AppKit                        	       0x189132390 -[NSApplication(NSEventRouting) sendEvent:] + 964
22  Codex Framework               	       0x1173fb184 v8::ScriptCompiler::CompileFunction(v8::Local<v8::Context>, v8::ScriptCompiler::Source*, unsigned long, v8::Local<v8::String>*, unsigned long, v8::Local<v8::Object>*, v8::ScriptCompiler::CompileOptions, v8::ScriptCompiler::NoCacheReason) + 128932
23  Codex Framework               	       0x115400794 v8::ValueSerializer::Delegate::HasCustomHostObject(v8::Isolate*) + 184212