-
Notifications
You must be signed in to change notification settings - Fork 88
fix: prevent zombie instances on app restart #23757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -144,8 +144,16 @@ extension AppDelegate { | |||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| @objc func performRestart() { | ||||||||||||||||||||||||||||||
| isRestarting = true | ||||||||||||||||||||||||||||||
| let bundleURL = Bundle.main.bundleURL | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Disconnect SSE and health checks *before* the CLI kills the | ||||||||||||||||||||||||||||||
| // daemon/gateway. Otherwise the health check detects the daemon | ||||||||||||||||||||||||||||||
| // dying, triggers autoWakeIfAssistantDied(), and wakes the daemon | ||||||||||||||||||||||||||||||
| // right back up — fighting with the shutdown. (Same pattern as | ||||||||||||||||||||||||||||||
| // performRetireAsync().) | ||||||||||||||||||||||||||||||
| connectionManager.disconnect() | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Write a timestamped sentinel so the new instance's single-instance | ||||||||||||||||||||||||||||||
| // guard knows this is an intentional restart, not a duplicate launch. | ||||||||||||||||||||||||||||||
| // The sentinel contains the current Unix timestamp; the new instance | ||||||||||||||||||||||||||||||
|
|
@@ -165,6 +173,13 @@ extension AppDelegate { | |||||||||||||||||||||||||||||
| // Clean up the sentinel so a failed restart doesn't leave | ||||||||||||||||||||||||||||||
| // a file that could bypass the guard on the next launch. | ||||||||||||||||||||||||||||||
| try? FileManager.default.removeItem(at: sentinelPath) | ||||||||||||||||||||||||||||||
| self?.isRestarting = false | ||||||||||||||||||||||||||||||
| // Reconnect SSE and health checks so the app doesn't stay | ||||||||||||||||||||||||||||||
| // in a disconnected state after a failed relaunch attempt. | ||||||||||||||||||||||||||||||
| // (Same pattern as performRetireAsync()'s cancel path.) | ||||||||||||||||||||||||||||||
| Task { @MainActor [weak self] in | ||||||||||||||||||||||||||||||
| try? await self?.connectionManager.connect() | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
Comment on lines
+176
to
+182
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴
On Apple Silicon (ARM64, weak memory model), the write may never become visible to the main actor. If the restart fails and
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
|
Jasonnnz marked this conversation as resolved.
|
||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| Task { @MainActor [weak self] in | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.