Skip to content

fix(desktop): register app:quit IPC handler to fix E2E quit hang#737

Merged
Siri-Ray merged 5 commits intomainfrom
worktree-fix+e2e-app-quit-ipc
Apr 1, 2026
Merged

fix(desktop): register app:quit IPC handler to fix E2E quit hang#737
Siri-Ray merged 5 commits intomainfrom
worktree-fix+e2e-app-quit-ipc

Conversation

@lefarcen
Copy link
Copy Markdown
Collaborator

@lefarcen lefarcen commented Apr 1, 2026

What

Register the missing app:quit IPC channel so E2E tests can cleanly exit the packaged app without hanging.

Why

Desktop E2E CI runs hang for ~14 minutes during app quit, then get cancelled by the CI timeout. Root cause: the E2E test calls window.nexuHost.invoke("app:quit") but that channel was never registered, causing a silent fallback to SIGTERM + osascript which doesn't reliably exit on headless CI.

Ref: https://github.com/nexu-io/nexu/actions/runs/23830575922

How

  • Add app:quit to hostInvokeChannels, HostInvokePayloadMap, and HostInvokeResultMap in shared/host.ts
  • Add IPC case handler in ipc.ts that delegates to the existing quitWithDecision() function
  • Add setQuitHandlerOpts() setter (same pattern as setUpdateManager) so the IPC handler can access quit options after launchd bootstrap
  • Wire up setQuitHandlerOpts() call in index.ts right after installLaunchdQuitHandler()
  • Harden E2E quitPackagedApp() with 15-second SIGKILL hard timeout on both IPC and SIGTERM fallback paths

Affected areas

  • Desktop app (Electron shell)
  • Controller (backend / API)
  • Web dashboard (React UI)
  • OpenClaw runtime
  • Skills
  • Shared schemas / packages
  • Build / CI / Tooling

Checklist

  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (1 unrelated flaky test: skill-dir-watcher-workspace)
  • pnpm generate-types run (if API routes/schemas changed)
  • No credentials or tokens in code or logs
  • No any types introduced (use unknown with narrowing)

Notes for reviewers

  • quitWithDecision() already existed in quit-handler.ts but was never callable from IPC — this PR just wires it up
  • The app:quit channel accepts { decision: "quit-completely" | "run-in-background" }, matching the existing QuitDecision type
  • If quitHandlerOpts is not yet set (cold start still in progress), falls back to app.exit(0) directly

The E2E test calls app:quit IPC to cleanly exit the packaged app, but
the channel was never registered. This caused the test to fall back to
SIGTERM + osascript, which hung indefinitely on CI (14 min timeout).

- Add app:quit to hostInvokeChannels, payload/result type maps
- Add IPC case handler that delegates to quitWithDecision()
- Add setQuitHandlerOpts() setter so IPC handler can access quit opts
- Harden E2E quit with 15s SIGKILL timeout on both IPC and SIGTERM paths
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 716dc07680

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/main/ipc.ts Outdated
lefarcen added 4 commits April 1, 2026 16:20
Address review feedback:
- Use runTeardownAndExit() (finally → app.exit(0)) instead of
  quitWithDecision() so the process always exits even if teardown throws
- Handle run-in-background separately (only hide window, no teardown)
- quitHandlerOpts null fallback still calls app.exit(0) directly
When quitHandlerOpts is null (CI / orchestrator mode), app:quit now
calls gracefulShutdown() via an injected fallback instead of bare
app.exit(0). This ensures orchestrator-managed child processes
(controller, web, openclaw) are properly cleaned up before exit.
@Siri-Ray Siri-Ray merged commit 39adf43 into main Apr 1, 2026
11 checks passed
@lefarcen lefarcen mentioned this pull request Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants