fix: close orphaned dev Electron app after Ctrl+C (#498)
This commit is contained in:
parent
aeb8002df7
commit
f43bf4f90e
|
|
@ -10,6 +10,7 @@ vi.mock('electron', () => {
|
|||
paths.set(name, value)
|
||||
}),
|
||||
quit: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
commandLine: {
|
||||
appendSwitch: vi.fn()
|
||||
}
|
||||
|
|
@ -50,6 +51,7 @@ describe('installDevParentDisconnectQuit', () => {
|
|||
const { app } = await import('electron')
|
||||
const { installDevParentDisconnectQuit } = await import('./configure-process')
|
||||
|
||||
vi.useFakeTimers()
|
||||
const originalSend = process.send
|
||||
const originalOnce = process.once.bind(process)
|
||||
const disconnectHandlers: (() => void)[] = []
|
||||
|
|
@ -74,6 +76,10 @@ describe('installDevParentDisconnectQuit', () => {
|
|||
expect(disconnectHandlers).toHaveLength(1)
|
||||
disconnectHandlers[0]()
|
||||
expect(app.quit).toHaveBeenCalledTimes(1)
|
||||
expect(app.exit).not.toHaveBeenCalled()
|
||||
|
||||
await vi.advanceTimersByTimeAsync(3000)
|
||||
expect(app.exit).toHaveBeenCalledWith(0)
|
||||
})
|
||||
|
||||
it('does not register the disconnect hook outside dev ipc launches', async () => {
|
||||
|
|
@ -104,6 +110,7 @@ describe('installDevParentWatchdog', () => {
|
|||
|
||||
vi.useFakeTimers()
|
||||
vi.mocked(app.quit).mockClear()
|
||||
vi.mocked(app.exit).mockClear()
|
||||
|
||||
let parentExists = true
|
||||
vi.spyOn(process, 'kill').mockImplementation(((
|
||||
|
|
@ -132,6 +139,10 @@ describe('installDevParentWatchdog', () => {
|
|||
parentExists = false
|
||||
await vi.advanceTimersByTimeAsync(1000)
|
||||
expect(app.quit).toHaveBeenCalledTimes(1)
|
||||
expect(app.exit).not.toHaveBeenCalled()
|
||||
|
||||
await vi.advanceTimersByTimeAsync(3000)
|
||||
expect(app.exit).toHaveBeenCalledWith(0)
|
||||
} finally {
|
||||
if (originalPpid) {
|
||||
Object.defineProperty(process, 'ppid', originalPpid)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,23 @@
|
|||
import { app } from 'electron'
|
||||
import { join } from 'path'
|
||||
|
||||
const DEV_PARENT_SHUTDOWN_GRACE_MS = 3000
|
||||
|
||||
function requestDevParentShutdown(): void {
|
||||
app.quit()
|
||||
|
||||
const forceExitTimer = setTimeout(() => {
|
||||
// Why: in dev, losing the supervising parent means this Electron process is
|
||||
// already orphaned from the terminal session. We try app.quit() first so
|
||||
// normal cleanup still runs, but fall back to app.exit() when macOS quit
|
||||
// handlers or window-close guards stall and would otherwise leave Orca
|
||||
// hanging after Ctrl+C ends `pnpm dev`.
|
||||
app.exit(0)
|
||||
}, DEV_PARENT_SHUTDOWN_GRACE_MS)
|
||||
|
||||
forceExitTimer.unref()
|
||||
}
|
||||
|
||||
export function installUncaughtPipeErrorGuard(): void {
|
||||
process.on('uncaughtException', (error) => {
|
||||
if (
|
||||
|
|
@ -66,7 +83,7 @@ export function installDevParentDisconnectQuit(isDev: boolean): void {
|
|||
// without terminating the app window, so in dev we quit explicitly when the
|
||||
// supervising IPC channel disconnects instead of leaving a stray Electron app.
|
||||
process.once('disconnect', () => {
|
||||
app.quit()
|
||||
requestDevParentShutdown()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +123,7 @@ export function installDevParentWatchdog(isDev: boolean): void {
|
|||
// the dev runner while leaving Orca open. Watching the original parent PID
|
||||
// keeps dev shutdown coupled to the terminal session without affecting the
|
||||
// packaged app, which is not supervised by electron-vite.
|
||||
app.quit()
|
||||
requestDevParentShutdown()
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue