mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-19 13:23:50 +03:00
fix(dev): allow Ctrl+C to promptly kill dev server by closing active connections (#13020)
* fix(dev): allow Ctrl+C to promptly kill dev server by closing active connections and adding force-exit timeout * test(dev): add regression assertions for prompt dev server exit on Ctrl+C * docs(changelog): add fragment for #13020
This commit is contained in:
1
changelog.d/fixes/13020-dev-server-ctrl-c-prompt-exit.md
Normal file
1
changelog.d/fixes/13020-dev-server-ctrl-c-prompt-exit.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(dev):** allow Ctrl+C to promptly kill dev server by closing active connections ([#13020](https://github.com/diegosouzapw/OmniRoute/pull/13020)) — thanks @tuandinh0801
|
||||
@@ -235,15 +235,31 @@ async function start() {
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
let isShuttingDown = false;
|
||||
const shutdown = async (signal) => {
|
||||
if (isShuttingDown) {
|
||||
// Second Ctrl+C / signal forces immediate exit
|
||||
process.exit(1);
|
||||
}
|
||||
isShuttingDown = true;
|
||||
|
||||
// Safety net: force exit after 2s if keep-alive sockets or Next.js app close hangs
|
||||
const forceExitTimer = setTimeout(() => {
|
||||
process.exit(0);
|
||||
}, 2000);
|
||||
forceExitTimer.unref?.();
|
||||
|
||||
systemdNotifier.stopping();
|
||||
try {
|
||||
server.closeIdleConnections?.();
|
||||
server.closeAllConnections?.();
|
||||
await new Promise((resolve) => server.close(resolve));
|
||||
await globalThis.__omnirouteRequestShutdown?.(signal);
|
||||
await nextApp.close();
|
||||
} catch (error) {
|
||||
console.error("[SHUTDOWN] Failed during signal:", signal, error);
|
||||
} finally {
|
||||
clearTimeout(forceExitTimer);
|
||||
process.exit(0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,3 +27,21 @@ test("the custom Next runner owns exit and awaits application cleanup before clo
|
||||
assert.ok(applicationCleanup < nextClose, "application cleanup must finish before Next closes");
|
||||
assert.ok(nextClose < processExit, "process exit must remain the final shutdown action");
|
||||
});
|
||||
|
||||
test("custom Next runner closes existing connections and supports force exit on Ctrl+C", () => {
|
||||
const closeAll = runNextSource.indexOf("server.closeAllConnections?.()");
|
||||
const serverClose = runNextSource.indexOf("server.close(resolve)");
|
||||
assert.ok(closeAll >= 0, "must close active/keep-alive connections to prevent hanging on Ctrl+C");
|
||||
assert.ok(closeAll < serverClose, "connections must be terminated before server.close wait");
|
||||
|
||||
assert.match(
|
||||
runNextSource,
|
||||
/if\s*\(\s*isShuttingDown\s*\)\s*\{\s*\/\/[^\n]*\n\s*process\.exit\(1\);?\s*\}/,
|
||||
"second signal / Ctrl+C must immediately exit"
|
||||
);
|
||||
assert.match(
|
||||
runNextSource,
|
||||
/setTimeout\(\(\)\s*=>\s*\{\s*process\.exit\(0\);?\s*\},\s*\d+\)/,
|
||||
"must have fallback force exit timer"
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user