mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-30 07:53:26 +08:00
fix(mcp): cap watchdog and startup-handshake timeouts at the largest timer delay (#1966)
Node runs a setTimeout delay above 2^31-1 ms after 1 ms instead, so a huge
CODEGRAPH_WATCHDOG_TIMEOUT_MS SIGKILLed a healthy server at once and a huge
CODEGRAPH_STARTUP_HANDSHAKE_TIMEOUT_MS abandoned the launch within
milliseconds. Both parsers now cap at 2147483647.
(cherry picked from commit a242f579ce)
This commit is contained in:
committed by
Colby McHenry
parent
71985f2620
commit
080ceed082
@@ -18,6 +18,13 @@ describe('config parsing', () => {
|
||||
expect(parseWatchdogTimeoutMs('1500')).toBe(1500);
|
||||
});
|
||||
|
||||
it('parseWatchdogTimeoutMs caps at the largest delay a timer can hold (#1966)', () => {
|
||||
// Node runs a setTimeout delay above 2^31-1 ms after 1 ms instead.
|
||||
expect(parseWatchdogTimeoutMs('2147483647')).toBe(2147483647);
|
||||
expect(parseWatchdogTimeoutMs('2147483648')).toBe(2147483647);
|
||||
expect(parseWatchdogTimeoutMs('3000000000')).toBe(2147483647);
|
||||
});
|
||||
|
||||
it('deriveCheckIntervalMs stays within [50, 2000] and scales with the timeout', () => {
|
||||
expect(deriveCheckIntervalMs(60_000)).toBe(2000); // clamped high
|
||||
expect(deriveCheckIntervalMs(500)).toBe(100); // 500/5
|
||||
@@ -90,6 +97,15 @@ describe('liveness watchdog (spawned, real watchdog process)', () => {
|
||||
expect(r.signal === 'SIGKILL' || (r.signal === null && r.code !== 0 && r.code !== null)).toBe(true);
|
||||
}
|
||||
|
||||
it('leaves a healthy process alone when the timeout is set past what a timer can hold (#1966)', async () => {
|
||||
const r = await runChild(
|
||||
{ CODEGRAPH_WATCHDOG_TIMEOUT_MS: '3000000000' },
|
||||
'setTimeout(() => process.exit(0), 1000);',
|
||||
8000
|
||||
);
|
||||
expect(r).toEqual({ code: 0, signal: null });
|
||||
}, 12000);
|
||||
|
||||
it('SIGKILLs a process whose main thread wedges in a sync loop', async () => {
|
||||
const r = await runChild(
|
||||
{ CODEGRAPH_WATCHDOG_TIMEOUT_MS: '500' },
|
||||
|
||||
@@ -38,6 +38,24 @@ describe('parseStartupHandshakeTimeoutMs', () => {
|
||||
it('floors fractional values', () => {
|
||||
expect(parseStartupHandshakeTimeoutMs('2500.7')).toBe(2500);
|
||||
});
|
||||
|
||||
it('caps at the largest delay a timer can hold (#1966)', () => {
|
||||
expect(parseStartupHandshakeTimeoutMs('2147483647')).toBe(2147483647);
|
||||
expect(parseStartupHandshakeTimeoutMs('2147483648')).toBe(2147483647);
|
||||
expect(parseStartupHandshakeTimeoutMs('3000000000')).toBe(2147483647);
|
||||
});
|
||||
|
||||
it('does not abandon a launch at once when the timeout is set past what a timer can hold (#1966)', async () => {
|
||||
let abandoned = false;
|
||||
const disarm = armStartupHandshakeTimeout(
|
||||
() => { abandoned = true; },
|
||||
new PassThrough(),
|
||||
parseStartupHandshakeTimeoutMs('3000000000'),
|
||||
);
|
||||
await sleep(100);
|
||||
disarm();
|
||||
expect(abandoned).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('armStartupHandshakeTimeout', () => {
|
||||
|
||||
Reference in New Issue
Block a user