host: watch BEAM child and re-spawn it on any exit - #4
Merged
Conversation
The host owns BEAM in packaged apps (host-first macOS layout, future Linux parity). Heart watches the launcher script and re-execs it; that fights the host's own process model where the host should drive restart. Install a child-exit handler in both the Swift (NSApp) macOS host and the C++ GTK Linux host. On any exit: - If quit is already in flight (Cmd+Q, prepare_quit RPC, or force-quit), do not respawn. - Otherwise, after an exponential backoff (500 ms -> 1 s -> 2 s -> 4 s -> 5 s cap), spawn the BEAM script again. - Optional restart_max_attempts cap (0 = forever). The host quits once the cap is reached, instead of looping forever on a persistent crash. Configurable via CLI flags --edw-restart-beam=, --edw-max-restart- attempts=, --edw-restart-backoff-ms= and INI keys [lifetime] restart_beam / restart_max_attempts / restart_backoff_ms. The existing system.prepare_quit RPC now also marks a 3 s "expected exit" window so user-driven shutdowns are not misread as crashes. Co-Authored-By: Claude <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
2 tasks
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
The native webview host now owns BEAM restart for packaged apps instead of
heart. This unblocks the host-first macOS bundle (and the equivalent Linux layout going forward) where the host — not the BEAM release — is the long-lived process.A child-exit watcher on both the Swift (macOS) and C++/GTK (Linux) controllers catches BEAM termination, applies an exponential backoff, and respawns. The host distinguishes a user-initiated shutdown from a crash using the existing
system.prepare_quitRPC, which marks a 3-second expected-exit window.Configurable via CLI flags and INI keys:
--edw-restart-beam=/[lifetime] restart_beam— turn respawn on/off (default: on)--edw-max-restart-attempts=/[lifetime] restart_max_attempts— 0 = forever (default)--edw-restart-backoff-ms=/[lifetime] restart_backoff_ms— base backoff in ms, exponential 1×→16× capped at 5 sWhen the attempt cap is hit, the host quits instead of looping forever on a persistently broken release.
Why this change
Heart watches the launcher shell script and re-execs it. That makes BEAM the long-lived process and the host a transient one, which is the opposite of what we want for the host-first bundle. With this change:
system.prepare_quitfrom Elixir tells the host "this exit is intentional" so it doesn't respawnUpdater.apply_update→OS.restart→kill -9) keeps working because the host picks up the kill and respawnsTest plan
DesktopWebView.iniwithrestart_beam = falsedisables respawnkill -9 $BEAM_PID) while DesktopWebView is running — host respawns BEAM within ~500 ms; verifyprepare_quitwas not sentOS.restart/0from Elixir — host respawns BEAM after the kill:init.stop()from Elixir, observe host does NOT respawn (prepare_quit is sent beforestop)restart_max_attempts = 2, repeatedly kill BEAM; after 2 restarts host itself quits--edw-restart-beam=falsedisables respawn entirely