diff --git a/packages/processing-control/src/runtimes.mjs b/packages/processing-control/src/runtimes.mjs index 05e439c1a..a11cb8e52 100644 --- a/packages/processing-control/src/runtimes.mjs +++ b/packages/processing-control/src/runtimes.mjs @@ -330,7 +330,7 @@ async function ownStop(args, key, options) { }; const termEnd = started + grace, deadline = termEnd + observe; let termTried = false, killTried = false; - while (now() <= deadline) { + for (;;) { try { record = runtime(root, record.id); } catch { const present = readdirSync(directory(root, 'runtimes')).includes(record.id + '.json'); diff --git a/packages/processing-control/tests/stop-run.test.mjs b/packages/processing-control/tests/stop-run.test.mjs index ed69bc111..5277ea7fe 100644 --- a/packages/processing-control/tests/stop-run.test.mjs +++ b/packages/processing-control/tests/stop-run.test.mjs @@ -61,6 +61,17 @@ test('failed signal delivery observes alive, records no invented signals and nev assert.equal(f.sleeps.reduce((a,b)=>a+b,0), 7000); assert.deepEqual(await stopRun(f.args, f.options), result); }); +test('a sleep past the stop deadline still observes an alive run after both signals', async t => { + const f = setup(t); let time = 0; + f.options.now = () => time; + f.options.sleep = async ms => { time += ms + 1; }; + f.options.signal = (_r, sig) => { f.signals.push(sig); return true; }; + const result = await stopRun(f.args, f.options); + assert.ok(time > 7000, 'the last sleep wakes past the complete stop deadline'); + assert.deepEqual(f.signals, ['SIGTERM', 'SIGKILL']); + assert.equal(result.outcome, 'alive'); + assert.deepEqual(result.signals, ['SIGTERM', 'SIGKILL']); +}); test('missing run and another business never borrow a pid or signal', async t => { const f = setup(t); for (const args of [{ ...f.args, run: 'missing' }, { ...f.args, business: 'other' }]) {