From 943e742917ac94714d2f408a0e8320f2d1fcafcd Mon Sep 17 00:00:00 2001 From: Trung Nguyen <57174311+trungnt2910@users.noreply.github.com> Date: Fri, 30 Dec 2022 09:37:40 +0700 Subject: [PATCH] fix: Retry on timeout (#106) * fix: do not set return value for timed out runs Commands that are killed manually due to timeout rarely returns a success status code (0). These codes should not be treated as errors but simply produced because of the timeout. * fix(windows): use variable to track timeout Use a variable to track timeout instead of relying on SIGTERM, as processes on Windows are not killed using signals. --- dist/index.js | 14 ++++++++++---- src/index.ts | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/dist/index.js b/dist/index.js index 4453af1..c5029cb 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1005,7 +1005,7 @@ function runRetryCmd(inputs) { function runCmd(attempt, inputs) { var _a, _b; return __awaiter(this, void 0, void 0, function () { - var end_time, executable, child; + var end_time, executable, timeout, child; return __generator(this, function (_c) { switch (_c.label) { case 0: @@ -1013,6 +1013,7 @@ function runCmd(attempt, inputs) { executable = getExecutable(inputs); exit = 0; done = false; + timeout = false; (0, core_1.debug)("Running command ".concat(inputs.command, " on ").concat(OS, " using shell ").concat(executable)); child = attempt > 1 && inputs.new_command_on_retry ? (0, child_process_1.spawn)(inputs.new_command_on_retry, { shell: executable }) @@ -1026,13 +1027,17 @@ function runCmd(attempt, inputs) { child.on('exit', function (code, signal) { (0, core_1.debug)("Code: ".concat(code)); (0, core_1.debug)("Signal: ".concat(signal)); - if (code && code > 0) { - exit = code; - } // timeouts are killed manually if (signal === 'SIGTERM') { return; } + // On Windows signal is null. + if (timeout) { + return; + } + if (code && code > 0) { + exit = code; + } done = true; }); _c.label = 1; @@ -1045,6 +1050,7 @@ function runCmd(attempt, inputs) { _c.label = 4; case 4: if (!(!done && child.pid)) return [3 /*break*/, 6]; + timeout = true; (0, tree_kill_1.default)(child.pid); return [4 /*yield*/, (0, util_1.retryWait)(milliseconds_1.default.seconds(inputs.retry_wait_seconds))]; case 5: diff --git a/src/index.ts b/src/index.ts index be0989b..f443451 100644 --- a/src/index.ts +++ b/src/index.ts @@ -71,6 +71,7 @@ async function runCmd(attempt: number, inputs: Inputs) { exit = 0; done = false; + let timeout = false; debug(`Running command ${inputs.command} on ${OS} using shell ${executable}`); const child = @@ -88,13 +89,21 @@ async function runCmd(attempt: number, inputs: Inputs) { child.on('exit', (code, signal) => { debug(`Code: ${code}`); debug(`Signal: ${signal}`); - if (code && code > 0) { - exit = code; - } + // timeouts are killed manually if (signal === 'SIGTERM') { return; } + + // On Windows signal is null. + if (timeout) { + return; + } + + if (code && code > 0) { + exit = code; + } + done = true; }); @@ -103,6 +112,7 @@ async function runCmd(attempt: number, inputs: Inputs) { } while (Date.now() < end_time && !done); if (!done && child.pid) { + timeout = true; kill(child.pid); await retryWait(ms.seconds(inputs.retry_wait_seconds)); throw new Error(`Timeout of ${getTimeout(inputs)}ms hit`);