Skip to content

Commit a57049c

Browse files
committed
fix: terminate background processes on app quit
Adds terminateAll() to BackgroundProcessManager and hooks it into Electron's before-quit event, preventing orphaned processes when mux exits normally. Crash recovery (orphans from SIGKILL) remains out of scope.
1 parent c5571f9 commit a57049c

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

src/desktop/main.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,18 @@ if (gotTheLock) {
540540
}
541541
});
542542

543+
// Track if we're already quitting to avoid re-entrancy
544+
let isQuitting = false;
545+
app.on("before-quit", (event) => {
546+
if (ipcMain && !isQuitting) {
547+
isQuitting = true;
548+
event.preventDefault();
549+
ipcMain.terminateAllBackgroundProcesses().finally(() => {
550+
app.exit(0);
551+
});
552+
}
553+
});
554+
543555
app.on("activate", () => {
544556
// Only create window if app is ready and no window exists
545557
// This prevents "Cannot create BrowserWindow before app is ready" error

src/node/services/backgroundProcessManager.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,16 @@ export class BackgroundProcessManager {
194194

195195
log.debug(`Cleaned up ${matching.length} process(es) for workspace ${workspaceId}`);
196196
}
197+
198+
/**
199+
* Terminate all background processes across all workspaces.
200+
* Called on app shutdown to prevent orphaned processes.
201+
*/
202+
async terminateAll(): Promise<void> {
203+
log.debug(`BackgroundProcessManager.terminateAll() called`);
204+
const allProcesses = Array.from(this.processes.values());
205+
await Promise.all(allProcesses.map((p) => this.terminate(p.id)));
206+
this.processes.clear();
207+
log.debug(`Terminated ${allProcesses.length} background process(es)`);
208+
}
197209
}

src/node/services/ipcMain.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ export class IpcMain {
112112
await this.extensionMetadata.initialize();
113113
}
114114

115+
/**
116+
* Terminate all background processes. Called on app shutdown.
117+
*/
118+
async terminateAllBackgroundProcesses(): Promise<void> {
119+
await this.backgroundProcessManager.terminateAll();
120+
}
121+
115122
/**
116123
* Configure a picker used to select project directories (desktop mode only).
117124
* Server mode does not provide a native directory picker.

0 commit comments

Comments
 (0)