From a18b4fb49a6085da708f5d6da30b27d0578a788b Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 29 Jul 2021 16:01:22 -0700 Subject: [PATCH] fix(test runner): workaround npm bug that sends multiple sigints (#7916) When running through NPM, we can get multiple SIGINT signals for a single Ctrl+C - the more npm layers you use, the more SIGINTs you get. This is a known NPM bug present since at least NPM v6. Workaround is to give NPM one second for the fake signals, and only then remove out listener. --- src/test/runner.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/test/runner.ts b/src/test/runner.ts index 60f874a96b..38d36ee6d9 100644 --- a/src/test/runner.ts +++ b/src/test/runner.ts @@ -273,11 +273,21 @@ export class Runner { let sigintCallback: () => void; const sigIntPromise = new Promise(f => sigintCallback = f); const sigintHandler = () => { - // We remove handler so that double Ctrl+C immediately kills the runner, - // for the case where our shutdown takes a lot of time or is buggy. - // Removing the handler synchronously sometimes triggers the default handler - // that exits the process, so we remove asynchronously. - setTimeout(() => process.off('SIGINT', sigintHandler), 0); + // We remove the handler so that second Ctrl+C immediately kills the runner + // via the default sigint handler. This is handy in the case where our shutdown + // takes a lot of time or is buggy. + // + // When running through NPM we might get multiple SIGINT signals + // for a single Ctrl+C - this is an NPM bug present since at least NPM v6. + // https://github.com/npm/cli/issues/1591 + // https://github.com/npm/cli/issues/2124 + // + // Therefore, removing the handler too soon will just kill the process + // with default handler without printing the results. + // We work around this by giving NPM 1000ms to send us duplicate signals. + // The side effect is that slow shutdown or bug in our runner will force + // the user to hit Ctrl+C again after at least a second. + setTimeout(() => process.off('SIGINT', sigintHandler), 1000); sigint = true; sigintCallback(); };