Skip to content

Commit b2260f5

Browse files
wyattjohmysticatea
authored andcommitted
🐛 fix signal handling (#171)
1 parent 5017a88 commit b2260f5

File tree

5 files changed

+66
-2
lines changed

5 files changed

+66
-2
lines changed

lib/run-task.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ module.exports = function runTask(task, options) {
189189
cp = null
190190
reject(err)
191191
})
192-
cp.on("close", (code) => {
192+
cp.on("close", (code, signal) => {
193193
cp = null
194-
resolve({ task, code })
194+
resolve({ task, code, signal })
195195
})
196196
})
197197

lib/run-tasks.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,39 @@ function remove(array, x) {
3232
}
3333
}
3434

35+
const signals = {
36+
SIGABRT: 6,
37+
SIGALRM: 14,
38+
SIGBUS: 10,
39+
SIGCHLD: 20,
40+
SIGCONT: 19,
41+
SIGFPE: 8,
42+
SIGHUP: 1,
43+
SIGILL: 4,
44+
SIGINT: 2,
45+
SIGKILL: 9,
46+
SIGPIPE: 13,
47+
SIGQUIT: 3,
48+
SIGSEGV: 11,
49+
SIGSTOP: 17,
50+
SIGTERM: 15,
51+
SIGTRAP: 5,
52+
SIGTSTP: 18,
53+
SIGTTIN: 21,
54+
SIGTTOU: 22,
55+
SIGUSR1: 30,
56+
SIGUSR2: 31,
57+
}
58+
59+
/**
60+
* Converts a signal name to a number.
61+
* @param {string} signal - the signal name to convert into a number
62+
* @returns {number} - the return code for the signal
63+
*/
64+
function convert(signal) {
65+
return signals[signal] || 0
66+
}
67+
3568
//------------------------------------------------------------------------------
3669
// Public Interface
3770
//------------------------------------------------------------------------------
@@ -133,6 +166,15 @@ module.exports = function runTasks(tasks, options) {
133166
originalOutputStream.write(writer.toString())
134167
}
135168

169+
// Check if the task failed as a result of a signal, and
170+
// amend the exit code as a result.
171+
if (result.code === null && result.signal !== null) {
172+
// An exit caused by a signal must return a status code
173+
// of 128 plus the value of the signal code.
174+
// Ref: https://nodejs.org/api/process.html#process_exit_codes
175+
result.code = 128 + convert(result.signal)
176+
}
177+
136178
// Save the result.
137179
results[task.index].code = result.code
138180

test-workspace/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"test-task:append:b": "node tasks/append2.js b",
2727
"test-task:append1": "node tasks/append1.js",
2828
"test-task:append2": "node tasks/append2.js",
29+
"test-task:abort": "node tasks/abort.js",
2930
"test-task:error": "node tasks/error.js",
3031
"test-task:stdout": "node tasks/stdout.js > test.txt",
3132
"test-task:stderr": "node tasks/stderr.js 2> test.txt",

test-workspace/tasks/abort.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"use strict"
2+
3+
setTimeout(() => {
4+
process.abort()
5+
}, 500)

test/fail.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,20 @@ describe("[fail] it should fail", () => {
101101
it("run-s command", () => shouldFail(runSeq(["test-task:error"])))
102102
it("run-p command", () => shouldFail(runPar(["test-task:error"])))
103103
})
104+
105+
describe("if tasks exited via a signal:", () => {
106+
it("Node API", () => shouldFail(nodeApi("test-task:abort")))
107+
it("npm-run-all command", () => shouldFail(runAll(["test-task:abort"])))
108+
it("run-s command", () => shouldFail(runSeq(["test-task:abort"])))
109+
it("run-p command", () => shouldFail(runPar(["test-task:abort"])))
110+
it("with correct exit code", () => nodeApi("test-task:abort").then(() =>
111+
assert(false, "should fail")
112+
).catch(err => {
113+
// In NodeJS versions > 6, the child process correctly sends back
114+
// the signal + code of null. In NodeJS versions <= 6, the child
115+
// process does not set the signal, and sets the code to 1.
116+
const code = Number(process.version.match(/^v(\d+)/)[1]) > 6 ? 134 : 1
117+
assert(err.code === code, "should have correct exit code")
118+
}))
119+
})
104120
})

0 commit comments

Comments
 (0)