📌 Description
In createShutdownHandler, clearTimeout(forceExit) only runs inside server.close's callback, after which exit(...) is called. If the callback body were to throw before reaching clearTimeout (or if exit itself throws, e.g. a test's injected exit mock), the forceExit timer is left armed and will still fire exit(1) later — potentially force-killing a process that already exited cleanly, or double-calling exit.
🧩 Requirements and context
- Move
clearTimeout(forceExit) to run unconditionally before any code that could throw, or wrap the callback body in a try/finally.
- Ensure
exit is still called with the correct code (0 on success, 1 on error) after the timer is safely cleared.
- Do not change the default
timeoutMs (10s) or the public ShutdownOptions signature.
🛠️ Suggested execution
- Modify
src/utils/shutdown.ts's createShutdownHandler to guard the server.close callback with try/finally around clearTimeout.
- Add a regression test in
src/utils/shutdown.test.ts using a fake exit that throws on its first call, asserting the forceExit timer doesn't later fire a second exit call.
✅ Acceptance criteria
🔒 Security notes
Low risk operational robustness fix — prevents a delayed, unintended forced-exit call after a clean shutdown already completed.
📋 Guidelines
- Minimum 95% test coverage
- Clear documentation
- Timeframe: 96 hours
📌 Description
In
createShutdownHandler,clearTimeout(forceExit)only runs insideserver.close's callback, after whichexit(...)is called. If the callback body were to throw before reachingclearTimeout(or ifexititself throws, e.g. a test's injectedexitmock), theforceExittimer is left armed and will still fireexit(1)later — potentially force-killing a process that already exited cleanly, or double-callingexit.🧩 Requirements and context
clearTimeout(forceExit)to run unconditionally before any code that could throw, or wrap the callback body in atry/finally.exitis still called with the correct code (0on success,1on error) after the timer is safely cleared.timeoutMs(10s) or the publicShutdownOptionssignature.🛠️ Suggested execution
src/utils/shutdown.ts'screateShutdownHandlerto guard theserver.closecallback withtry/finallyaroundclearTimeout.src/utils/shutdown.test.tsusing a fakeexitthat throws on its first call, asserting theforceExittimer doesn't later fire a secondexitcall.✅ Acceptance criteria
forceExitis always cleared onceserver.close's callback runs, even if subsequent code throws.🔒 Security notes
Low risk operational robustness fix — prevents a delayed, unintended forced-exit call after a clean shutdown already completed.
📋 Guidelines