From 93e7d83c3347bff291af378617c55b001267e58f Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 15 May 2026 10:50:28 +0530 Subject: [PATCH 1/2] fix: handle SIGINT/SIGTERM for graceful shutdown in Docker Dev and start commands now close Vite server and exit on SIGINT/SIGTERM. Fixes Docker container not stopping on Ctrl+C. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/chronicle/src/cli/commands/dev.ts | 7 +++++++ packages/chronicle/src/cli/commands/start.ts | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/packages/chronicle/src/cli/commands/dev.ts b/packages/chronicle/src/cli/commands/dev.ts index 80a19f96..728b9eb9 100644 --- a/packages/chronicle/src/cli/commands/dev.ts +++ b/packages/chronicle/src/cli/commands/dev.ts @@ -28,4 +28,11 @@ export const devCommand = new Command('dev') await server.listen(); server.printUrls(); + + const shutdown = async () => { + await server.close(); + process.exit(0); + }; + process.on('SIGINT', shutdown); + process.on('SIGTERM', shutdown); }); diff --git a/packages/chronicle/src/cli/commands/start.ts b/packages/chronicle/src/cli/commands/start.ts index 7be31f26..4ec6816c 100644 --- a/packages/chronicle/src/cli/commands/start.ts +++ b/packages/chronicle/src/cli/commands/start.ts @@ -26,4 +26,8 @@ export const startCommand = new Command('start') }); server.printUrls(); + + const shutdown = () => process.exit(0); + process.on('SIGINT', shutdown); + process.on('SIGTERM', shutdown); }); From d0235d9f99b5fdc88c8dbe7d562119db62ea206f Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 15 May 2026 11:03:03 +0530 Subject: [PATCH 2/2] fix: idempotent shutdown with try/catch and re-entrance guard - process.once instead of process.on to prevent double-fire - shuttingDown flag guards re-entrance - try/catch around server.close() to handle errors - start command now calls server.close() before exit Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/chronicle/src/cli/commands/dev.ts | 11 ++++++++--- packages/chronicle/src/cli/commands/start.ts | 14 +++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/chronicle/src/cli/commands/dev.ts b/packages/chronicle/src/cli/commands/dev.ts index 728b9eb9..ee67b290 100644 --- a/packages/chronicle/src/cli/commands/dev.ts +++ b/packages/chronicle/src/cli/commands/dev.ts @@ -29,10 +29,15 @@ export const devCommand = new Command('dev') await server.listen(); server.printUrls(); + let shuttingDown = false; const shutdown = async () => { - await server.close(); + if (shuttingDown) return; + shuttingDown = true; + try { + await server.close(); + } catch { /* ignore close errors */ } process.exit(0); }; - process.on('SIGINT', shutdown); - process.on('SIGTERM', shutdown); + process.once('SIGINT', shutdown); + process.once('SIGTERM', shutdown); }); diff --git a/packages/chronicle/src/cli/commands/start.ts b/packages/chronicle/src/cli/commands/start.ts index 4ec6816c..4bb86b3f 100644 --- a/packages/chronicle/src/cli/commands/start.ts +++ b/packages/chronicle/src/cli/commands/start.ts @@ -27,7 +27,15 @@ export const startCommand = new Command('start') server.printUrls(); - const shutdown = () => process.exit(0); - process.on('SIGINT', shutdown); - process.on('SIGTERM', shutdown); + let shuttingDown = false; + const shutdown = async () => { + if (shuttingDown) return; + shuttingDown = true; + try { + await server.close(); + } catch { /* ignore close errors */ } + process.exit(0); + }; + process.once('SIGINT', shutdown); + process.once('SIGTERM', shutdown); });