Skip to content

Commit 55ffa9a

Browse files
committed
fixes #6
1 parent cf60bdf commit 55ffa9a

File tree

4 files changed

+71
-8
lines changed

4 files changed

+71
-8
lines changed

src/index.js

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,21 @@ function defineExec() {
8181
return command => spawn("/bin/sh", ["-c", command]);
8282
}
8383

84+
function defineKillTask() {
85+
if (process.platform === "win32") {
86+
return cp => { spawn("taskkill", ["/F", "/T", "/PID", cp.pid]); };
87+
}
88+
return cp => { cp.kill(); };
89+
}
90+
8491
const exec = defineExec();
92+
const killTask = defineKillTask();
8593

8694
function runTask(task, stdin, stdout, stderr) {
87-
return new Promise((resolve, reject) => {
95+
let cp = null;
96+
const promise = new Promise((resolve, reject) => {
8897
// Execute.
89-
const cp = exec(`npm run-script ${task}`);
98+
cp = exec(`npm run-script ${task}`);
9099

91100
// Piping stdio.
92101
if (stdin) { stdin.pipe(cp.stdin); }
@@ -95,15 +104,27 @@ function runTask(task, stdin, stdout, stderr) {
95104

96105
// Register
97106
cp.on("exit", code => {
107+
cp = null;
98108
if (code) {
99109
reject(new Error(`${task}: None-Zero Exit(${code});`));
100110
}
101111
else {
102112
resolve(null);
103113
}
104114
});
105-
cp.on("error", reject);
115+
cp.on("error", err => {
116+
cp = null;
117+
reject(err);
118+
});
106119
});
120+
121+
promise.kill = function kill() {
122+
if (cp != null) {
123+
killTask(cp);
124+
}
125+
};
126+
127+
return promise;
107128
}
108129

109130
//------------------------------------------------------------------------------
@@ -133,7 +154,15 @@ export default function runAll(_tasks, _options) {
133154
}
134155

135156
if (parallel) {
136-
return Promise.all(tasks.map(task => runTask(task, stdin, stdout, stderr)));
157+
const taskPromises = tasks.map(task => runTask(task, stdin, stdout, stderr));
158+
const parallelPromise = Promise.all(taskPromises);
159+
160+
// When one of tasks crashed, kill all tasks.
161+
parallelPromise.catch(() => {
162+
taskPromises.forEach(t => t.kill());
163+
});
164+
165+
return parallelPromise;
137166
}
138167
return (function next() {
139168
const task = tasks.shift();

test/common.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,4 @@ describe("npm-run-all", () => {
101101
});
102102
});
103103
});
104-
105104
});

test/lib/util.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ exports.removeResult = function removeResult() {
2222
try {
2323
fs.unlinkSync(FILE_NAME);
2424
}
25-
catch (err) {} //eslint-disable-line no-empty
25+
catch (err) {
26+
if (err.message.indexOf("ENOENT") < 0) {
27+
console.error("ERROR:", err.stack);
28+
}
29+
}
2630
};
2731

2832

@@ -32,7 +36,13 @@ var BufferStream = exports.BufferStream = function BufferStream() {
3236
};
3337
inherits(BufferStream, Writable);
3438

35-
BufferStream.prototype._write = function(chunk, encoding, callback) { //eslint-disable-line no-underscore-dangle
39+
BufferStream.prototype._write = function _write(chunk, encoding, callback) {
3640
this.value += chunk.toString();
3741
callback();
3842
};
43+
44+
exports.delay = function delay(timeout) {
45+
return new Promise(function(resolve) {
46+
setTimeout(resolve, timeout);
47+
});
48+
};

test/parallel.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import assert from "power-assert";
2-
import {result, removeResult} from "./lib/util";
2+
import {result, removeResult, delay} from "./lib/util";
33

44
// Test targets.
55
import runAll from "../src/index";
@@ -33,4 +33,29 @@ describe("npm-run-all", () => {
3333
});
3434
});
3535

36+
describe("should kill all tasks when was given --parallel option if a task exited with non-zero code:", () => {
37+
it("lib version", () => {
38+
return runAll(["test-task:append a", "test-task:error"], {parallel: true})
39+
.then(() => delay(1500))
40+
.then(
41+
() => {
42+
assert(false, "should fail");
43+
},
44+
() => {
45+
assert(result() == null || result() === "a");
46+
});
47+
});
48+
49+
it("command version", () => {
50+
return command(["--parallel", "test-task:append a", "test-task:error"])
51+
.then(() => delay(1500))
52+
.then(
53+
() => {
54+
assert(false, "should fail");
55+
},
56+
() => {
57+
assert(result() == null || result() === "a");
58+
});
59+
});
60+
});
3661
});

0 commit comments

Comments
 (0)