Skip to content

Commit 5bfc7a7

Browse files
beautyfreeclaude
andauthored
Fix CI hang: exit on termination signals and watchdog smoke test (#31)
The SIGINT/SIGTERM/SIGHUP handlers in runtime-diagnostics only logged the signal name without calling process.exit. Registering a handler that does not exit overrides Node's default termination behavior, so the server ignored shutdown signals. The MCP SDK smoke test sends SIGTERM via StdioClientTransport.close, so the child server stayed alive and the "Run tests" job in the publish workflow hung until the workflow timeout. Make the handlers log and then exit cleanly, and add a 60s hard timeout to the smoke test so any future regression in shutdown can never hang CI for hours. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 17f956a commit 5bfc7a7

2 files changed

Lines changed: 23 additions & 4 deletions

File tree

scripts/mcp-smoke-test.mjs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,21 @@ async function main() {
9595
}
9696
}
9797

98-
main().catch((error) => {
99-
console.error('MCP smoke test failed:', error);
100-
process.exit(1);
101-
});
98+
// Hard timeout so a stuck child process can never hang CI for hours.
99+
const SMOKE_TEST_TIMEOUT_MS = 60_000;
100+
const watchdog = setTimeout(() => {
101+
console.error(`MCP smoke test timed out after ${SMOKE_TEST_TIMEOUT_MS}ms`);
102+
process.exit(2);
103+
}, SMOKE_TEST_TIMEOUT_MS);
104+
watchdog.unref();
105+
106+
main()
107+
.then(() => {
108+
clearTimeout(watchdog);
109+
process.exit(0);
110+
})
111+
.catch((error) => {
112+
clearTimeout(watchdog);
113+
console.error('MCP smoke test failed:', error);
114+
process.exit(1);
115+
});

src/runtime-diagnostics.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ export function installRuntimeDiagnostics() {
2121
logInfo(`MCP Linear exit with code ${code}`);
2222
});
2323

24+
// Log the signal then exit. Without the explicit exit Node treats the
25+
// registered handler as overriding default termination behavior, which
26+
// makes the server ignore SIGTERM/SIGINT/SIGHUP and hang in CI when
27+
// the smoke test or a parent process tries to shut it down.
2428
for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP'] as const) {
2529
process.on(signal, () => {
2630
logInfo(`MCP Linear received ${signal}`);
31+
process.exit(0);
2732
});
2833
}
2934
}

0 commit comments

Comments
 (0)