Skip to content

Commit 2bc177a

Browse files
cjihrigBridgeAR
authored andcommitted
child_process: setup stdio on error when possible
As more spawn() errors are classified as runtime errors, it's no longer appropriate to only check UV_ENOENT when determining if stdio can be setup. This commit reverses the check to look for EMFILE and ENFILE specifically. PR-URL: #27696 Fixes: #26852 Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 10b4a81 commit 2bc177a

File tree

3 files changed

+19
-4
lines changed

3 files changed

+19
-4
lines changed

lib/internal/child_process.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,11 @@ ChildProcess.prototype.spawn = function(options) {
375375
err === UV_ENFILE ||
376376
err === UV_ENOENT) {
377377
process.nextTick(onErrorNT, this, err);
378+
378379
// There is no point in continuing when we've hit EMFILE or ENFILE
379380
// because we won't be able to set up the stdio file descriptors.
380-
// It's kind of silly that the de facto spec for ENOENT (the test suite)
381-
// mandates that stdio _is_ set up, even if there is no process on the
382-
// receiving end, but it is what it is.
383-
if (err !== UV_ENOENT) return err;
381+
if (err === UV_EMFILE || err === UV_ENFILE)
382+
return err;
384383
} else if (err) {
385384
// Close all opened fds on error
386385
for (i = 0; i < stdio.length; i++) {

test/parallel/test-child-process-spawn-error.js

+10
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ const spawnargs = ['bar'];
3030
assert.strictEqual(fs.existsSync(enoentPath), false);
3131

3232
const enoentChild = spawn(enoentPath, spawnargs);
33+
34+
// Verify that stdio is setup if the error is not EMFILE or ENFILE.
35+
assert.notStrictEqual(enoentChild.stdin, undefined);
36+
assert.notStrictEqual(enoentChild.stdout, undefined);
37+
assert.notStrictEqual(enoentChild.stderr, undefined);
38+
assert(Array.isArray(enoentChild.stdio));
39+
assert.strictEqual(enoentChild.stdio[0], enoentChild.stdin);
40+
assert.strictEqual(enoentChild.stdio[1], enoentChild.stdout);
41+
assert.strictEqual(enoentChild.stdio[2], enoentChild.stderr);
42+
3343
enoentChild.on('error', common.mustCall(function(err) {
3444
assert.strictEqual(err.code, 'ENOENT');
3545
assert.strictEqual(err.errno, 'ENOENT');

test/sequential/test-child-process-emfile.js

+6
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ for (;;) {
5858
// Should emit an error, not throw.
5959
const proc = child_process.spawn(process.execPath, ['-e', '0']);
6060

61+
// Verify that stdio is not setup on EMFILE or ENFILE.
62+
assert.strictEqual(proc.stdin, undefined);
63+
assert.strictEqual(proc.stdout, undefined);
64+
assert.strictEqual(proc.stderr, undefined);
65+
assert.strictEqual(proc.stdio, undefined);
66+
6167
proc.on('error', common.mustCall(function(err) {
6268
assert.strictEqual(err.code, 'EMFILE');
6369
}));

0 commit comments

Comments
 (0)