From 45060742c3f4b2d345626fe6db3369ff9d4ac8ca Mon Sep 17 00:00:00 2001 From: teamleaderleo Date: Fri, 25 Sep 2026 16:39:50 -0400 Subject: [PATCH 1/2] Run the Codex monitor Stop replay outside the hook handler frame The codex monitor replayed Stop by calling runGenericAgentHook from a closure inside runGenericAgentHook, so two copies of that very large frame were live at once on the CLI's 512 KB cooperative-pool stack. The monitor now returns the replay and a thin dispatcher runs the Stop event after the monitor frame unwinds. The handler body is @inline(never) so it is never merged into the dispatcher. Co-Authored-By: Claude Opus 5.5 --- CLI/cmux.swift | 95 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 28 deletions(-) diff --git a/CLI/cmux.swift b/CLI/cmux.swift index 27c5ece1111c..88bbcc9d6dc1 100644 --- a/CLI/cmux.swift +++ b/CLI/cmux.swift @@ -30678,11 +30678,15 @@ struct CMUXCLI { } } + /// Watches the Codex rollout until the turn settles. + /// + /// Returns the Stop replay for a healthy completion instead of running it, + /// so the caller runs the Stop event after this frame has unwound. See + /// `runGenericAgentHook`. private func runCodexTranscriptMonitor( commandArgs: [String], - client: SocketClient, - replayStop: (CodexTranscriptMonitorStopReplay) throws -> Void - ) throws { + client: SocketClient + ) -> CodexTranscriptMonitorStopReplay? { let env = ProcessInfo.processInfo.environment let workspaceId = optionValue(commandArgs, name: "--workspace") ?? env["CMUX_WORKSPACE_ID"] ?? "" let surfaceId = optionValue(commandArgs, name: "--surface") ?? env["CMUX_SURFACE_ID"] @@ -30697,7 +30701,7 @@ struct CMUXCLI { guard !workspaceId.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty, !sessionId.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { - return + return nil } defer { removeCodexMonitorLease(path: leasePath) } @@ -30706,13 +30710,13 @@ struct CMUXCLI { var publishedUserInputCallIds = Set() while Date() < deadline { if isCodexMonitorLeaseRetired(path: leasePath) { - return + return nil } let now = Date() if now >= nextOwnerCheck { nextOwnerCheck = now.addingTimeInterval(Self.codexMonitorOwnerCheckIntervalSeconds) if codexMonitorOwnerState(workspaceId: workspaceId, surfaceId: surfaceId, client: client) == .gone { - return + return nil } } @@ -30741,19 +30745,16 @@ struct CMUXCLI { surfaceId: surfaceId, client: client ) - return + return nil case .healthy(let lastAssistantMessage): - if let replay = CodexTranscriptMonitorStopReplay( + return CodexTranscriptMonitorStopReplay( sessionId: sessionId, turnId: turnId, transcriptPath: currentTranscriptPath, workspaceId: workspaceId, surfaceId: surfaceId, lastAssistantMessage: lastAssistantMessage - ) { - try replayStop(replay) - } - return + ) case .pending: break case .unavailable: @@ -30769,9 +30770,10 @@ struct CMUXCLI { } let remaining = deadline.timeIntervalSinceNow - guard remaining > 0 else { return } + guard remaining > 0 else { return nil } waitForCodexTranscriptChange(path: transcriptPath, leasePath: leasePath, timeout: min(30, remaining)) } + return nil } private func publishCodexMonitorUserInput( @@ -33827,6 +33829,16 @@ export default CMUXSessionRestore; return normalizedHookValue(env["CMUX_SURFACE_ID"]) ?? "" } + /// Runs one agent hook event. + /// + /// `codex monitor` is the one event that leads to another: when the + /// rollout completes, the monitor replays a Stop event. That replay must + /// not run inside the event handler's own frame. The handler frame is very + /// large (about 175 KB of inlined locals), and the CLI runs on a Swift + /// concurrency thread with a 512 KB stack, so two nested handler frames + /// overflowed it (SIGBUS). The monitor returns the replay, and this + /// dispatcher runs it after the monitor returns, so at most one handler + /// frame is live at a time. private func runGenericAgentHook( def: AgentHookDef, commandArgs: [String], @@ -33835,6 +33847,48 @@ export default CMUXSessionRestore; socketPassword: String? = nil, rawInputOverride: String? = nil, hookDeadline: Date? = nil + ) throws { + guard def.name == "codex", commandArgs.first?.lowercased() == "monitor" else { + try runGenericAgentHookEvent( + def: def, + commandArgs: commandArgs, + client: client, + telemetry: telemetry, + socketPassword: socketPassword, + rawInputOverride: rawInputOverride, + hookDeadline: hookDeadline + ) + return + } + telemetry.breadcrumb("\(def.name)-hook.monitor") + guard let replay = runCodexTranscriptMonitor( + commandArgs: Array(commandArgs.dropFirst()), + client: client + ) else { + return + } + try runGenericAgentHookEvent( + def: def, + commandArgs: replay.commandArguments, + client: client, + telemetry: telemetry, + socketPassword: socketPassword, + rawInputOverride: replay.payload, + hookDeadline: hookDeadline + ) + } + + /// Handles a single agent hook event. Kept out of line so its large frame + /// is never merged into `runGenericAgentHook`, and never re-entered. + @inline(never) + private func runGenericAgentHookEvent( + def: AgentHookDef, + commandArgs: [String], + client: SocketClient, + telemetry: CLISocketSentryTelemetry, + socketPassword: String?, + rawInputOverride: String?, + hookDeadline: Date? ) throws { let env = ProcessInfo.processInfo.environment let skipCodexLegacyPromptStop = env["CMUX_CODEX_SETTLED_CHILD_STOP"] == "1" @@ -33874,21 +33928,6 @@ export default CMUXSessionRestore; } } - if def.name == "codex", subcommand == "monitor" { - try runCodexTranscriptMonitor(commandArgs: hookArgs, client: client) { replay in - try runGenericAgentHook( - def: def, - commandArgs: replay.commandArguments, - client: client, - telemetry: telemetry, - socketPassword: socketPassword, - rawInputOverride: replay.payload, - hookDeadline: hookDeadline - ) - } - return - } - if def.name == "codex", subcommand == "sync-native-title" { runCodexNativeTitleSyncHook( commandArgs: hookArgs, From ad18184348687fc3f47a28c3134ef6f24956fe11 Mon Sep 17 00:00:00 2001 From: teamleaderleo Date: Fri, 25 Sep 2026 16:42:09 -0400 Subject: [PATCH 2/2] Keep the Codex monitor frame out of line Co-Authored-By: Claude Opus 5.5 --- CLI/cmux.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CLI/cmux.swift b/CLI/cmux.swift index 88bbcc9d6dc1..6e26646c7696 100644 --- a/CLI/cmux.swift +++ b/CLI/cmux.swift @@ -30682,7 +30682,9 @@ struct CMUXCLI { /// /// Returns the Stop replay for a healthy completion instead of running it, /// so the caller runs the Stop event after this frame has unwound. See - /// `runGenericAgentHook`. + /// `runGenericAgentHook`. Kept out of line so its locals are gone before + /// the replayed Stop runs. + @inline(never) private func runCodexTranscriptMonitor( commandArgs: [String], client: SocketClient