Skip to content

Commit 373402f

Browse files
committed
process: swallow stdout/stderr error events
This is a step in making `console` safe, swallows EPIPE and other errors by registering an empty 'error' event listener. Also fixes writes to stdout/stderr not working after `end()` is called, even though we already override `destroy()` so the stream is never actually closed. Refs: nodejs#831 Fixes: nodejs#947 Fixes: nodejs#9403
1 parent 690bded commit 373402f

File tree

4 files changed

+46
-13
lines changed

4 files changed

+46
-13
lines changed

Diff for: lib/internal/process/stdio.js

+38
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,64 @@ function setupStdio() {
88
function getStdout() {
99
if (stdout) return stdout;
1010
stdout = createWritableStdioStream(1);
11+
12+
Object.defineProperty(stdout._writableState, 'ended', {
13+
set() {},
14+
get() {
15+
return false;
16+
}
17+
});
18+
// XXX(Fishrock123): This should work I think, but it causes
19+
// problems with some child-process related tests.
20+
//
21+
// Object.defineProperty(stdout, 'destroyed', {
22+
// set() {},
23+
// get() {
24+
// return true;
25+
// }
26+
// });
27+
1128
stdout.destroy = stdout.destroySoon = function(er) {
29+
stdout.destroyed = true;
1230
er = er || new Error('process.stdout cannot be closed.');
1331
stdout.emit('error', er);
1432
};
1533
if (stdout.isTTY) {
1634
process.on('SIGWINCH', () => stdout._refreshSize());
1735
}
36+
stdout.on('error', () => {});
1837
return stdout;
1938
}
2039

2140
function getStderr() {
2241
if (stderr) return stderr;
2342
stderr = createWritableStdioStream(2);
43+
44+
Object.defineProperty(stderr._writableState, 'ended', {
45+
set() {},
46+
get() {
47+
return false;
48+
}
49+
});
50+
// XXX(Fishrock123): This should work I think, but it causes
51+
// problems with some child-process related tests.
52+
//
53+
// Object.defineProperty(stderr, 'destroyed', {
54+
// set() {},
55+
// get() {
56+
// return true;
57+
// }
58+
// });
59+
2460
stderr.destroy = stderr.destroySoon = function(er) {
61+
stderr.destroyed = true;
2562
er = er || new Error('process.stderr cannot be closed.');
2663
stderr.emit('error', er);
2764
};
2865
if (stderr.isTTY) {
2966
process.on('SIGWINCH', () => stderr._refreshSize());
3067
}
68+
stderr.on('error', () => {});
3169
return stderr;
3270
}
3371

Diff for: test/parallel/test-stdout-cannot-be-closed-child-process-pipe.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ function parent() {
2424
});
2525

2626
child.on('close', function(code, signal) {
27-
assert(code);
27+
assert.strictEqual(code, 0, 'exit code should be zero');
2828
assert.equal(out, 'foo');
29-
assert(/process\.stdout cannot be closed/.test(err));
29+
assert.strictEqual(err, '', 'stderr should be empty');
3030
console.log('ok');
3131
});
3232
}

Diff for: test/pseudo-tty/test-tty-stdout-end.js

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
'use strict';
2-
require('../common');
2+
const common = require('../common');
33
const assert = require('assert');
44

5-
const shouldThrow = function() {
6-
process.stdout.end();
7-
};
8-
9-
const validateError = function(e) {
10-
return e instanceof Error &&
11-
e.message === 'process.stdout cannot be closed.';
12-
};
13-
14-
assert.throws(shouldThrow, validateError);
5+
process.stdout.on('error', common.mustCall(function(e) {
6+
assert(e instanceof Error, 'e is an Error');
7+
assert.strictEqual(e.message, 'process.stdout cannot be closed.');
8+
}));
9+
process.stdout.end();

0 commit comments

Comments
 (0)