Skip to content

Commit dd5b960

Browse files
committed
process: allow reading from stdout/stderr sockets
Allow reading from stdio streams that are conventionally associated with process output, since this is only convention. This involves disabling the oddness around closing stdio streams. Its purpose is to prevent the file descriptors 0 through 2 from being closed, since doing so can lead to information leaks when new file descriptors are being opened; instead, not doing anything seems like a more reasonable choice. Fixes: nodejs#21203
1 parent 4467b66 commit dd5b960

8 files changed

+30
-21
lines changed

doc/api/errors.md

+16
Original file line numberDiff line numberDiff line change
@@ -1552,12 +1552,28 @@ A call was made and the UDP subsystem was not running.
15521552

15531553
<a id="ERR_STDERR_CLOSE"></a>
15541554
### ERR_STDERR_CLOSE
1555+
<!-- YAML
1556+
changes:
1557+
- version: REPLACEME
1558+
pr-url: https://github.com/nodejs/node/pull/???
1559+
description: Rather than emitting an error, `process.stderr.end()` now
1560+
only closes the stream side but not the underlying resource,
1561+
making this error obsolete.
1562+
-->
15551563

15561564
An attempt was made to close the `process.stderr` stream. By design, Node.js
15571565
does not allow `stdout` or `stderr` streams to be closed by user code.
15581566

15591567
<a id="ERR_STDOUT_CLOSE"></a>
15601568
### ERR_STDOUT_CLOSE
1569+
<!-- YAML
1570+
changes:
1571+
- version: REPLACEME
1572+
pr-url: https://github.com/nodejs/node/pull/???
1573+
description: Rather than emitting an error, `process.stderr.end()` now
1574+
only closes the stream side but not the underlying resource,
1575+
making this error obsolete.
1576+
-->
15611577

15621578
An attempt was made to close the `process.stdout` stream. By design, Node.js
15631579
does not allow `stdout` or `stderr` streams to be closed by user code.

doc/api/process.md

+1-5
Original file line numberDiff line numberDiff line change
@@ -1860,9 +1860,7 @@ important ways:
18601860

18611861
1. They are used internally by [`console.log()`][] and [`console.error()`][],
18621862
respectively.
1863-
2. They cannot be closed ([`end()`][] will throw).
1864-
3. They will never emit the [`'finish'`][] event.
1865-
4. Writes may be synchronous depending on what the stream is connected to
1863+
2. Writes may be synchronous depending on what the stream is connected to
18661864
and whether the system is Windows or POSIX:
18671865
- Files: *synchronous* on Windows and POSIX
18681866
- TTYs (Terminals): *asynchronous* on Windows, *synchronous* on POSIX
@@ -2087,7 +2085,6 @@ cases:
20872085
code will be `128` + `6`, or `134`.
20882086

20892087
[`'exit'`]: #process_event_exit
2090-
[`'finish'`]: stream.html#stream_event_finish
20912088
[`'message'`]: child_process.html#child_process_event_message
20922089
[`'rejectionHandled'`]: #process_event_rejectionhandled
20932090
[`'uncaughtException'`]: #process_event_uncaughtexception
@@ -2101,7 +2098,6 @@ cases:
21012098
[`console.error()`]: console.html#console_console_error_data_args
21022099
[`console.log()`]: console.html#console_console_log_data_args
21032100
[`domain`]: domain.html
2104-
[`end()`]: stream.html#stream_writable_end_chunk_encoding_callback
21052101
[`net.Server`]: net.html#net_class_net_server
21062102
[`net.Socket`]: net.html#net_class_net_socket
21072103
[`NODE_OPTIONS`]: cli.html#cli_node_options_options

lib/internal/errors.js

-2
Original file line numberDiff line numberDiff line change
@@ -810,8 +810,6 @@ E('ERR_SOCKET_BUFFER_SIZE',
810810
E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data', Error);
811811
E('ERR_SOCKET_CLOSED', 'Socket is closed', Error);
812812
E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running', Error);
813-
E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed', Error);
814-
E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed', Error);
815813
E('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable', Error);
816814
E('ERR_STREAM_DESTROYED', 'Cannot call %s after a stream was destroyed', Error);
817815
E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);

lib/internal/process/stdio.js

+6-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
'use strict';
22

33
const {
4-
ERR_STDERR_CLOSE,
5-
ERR_STDOUT_CLOSE,
64
ERR_UNKNOWN_STDIN_TYPE,
75
ERR_UNKNOWN_STREAM_TYPE
86
} = require('internal/errors').codes;
97

108
exports.setupProcessStdio = setupProcessStdio;
119
exports.getMainThreadStdio = getMainThreadStdio;
1210

11+
function dummyDestroy(err, cb) { cb(err); }
12+
1313
function getMainThreadStdio() {
1414
var stdin;
1515
var stdout;
@@ -19,11 +19,8 @@ function getMainThreadStdio() {
1919
if (stdout) return stdout;
2020
stdout = createWritableStdioStream(1);
2121
stdout.destroySoon = stdout.destroy;
22-
stdout._destroy = function(er, cb) {
23-
// Avoid errors if we already emitted
24-
er = er || new ERR_STDOUT_CLOSE();
25-
cb(er);
26-
};
22+
// Override _destroy so that the fd is never actually closed.
23+
stdout._destroy = dummyDestroy;
2724
if (stdout.isTTY) {
2825
process.on('SIGWINCH', () => stdout._refreshSize());
2926
}
@@ -34,11 +31,8 @@ function getMainThreadStdio() {
3431
if (stderr) return stderr;
3532
stderr = createWritableStdioStream(2);
3633
stderr.destroySoon = stderr.destroy;
37-
stderr._destroy = function(er, cb) {
38-
// Avoid errors if we already emitted
39-
er = er || new ERR_STDERR_CLOSE();
40-
cb(er);
41-
};
34+
// Override _destroy so that the fd is never actually closed.
35+
stdout._destroy = dummyDestroy;
4236
if (stderr.isTTY) {
4337
process.on('SIGWINCH', () => stderr._refreshSize());
4438
}

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);
28+
assert.strictEqual(err, '');
2829
assert.strictEqual(out, 'foo');
29-
assert(/process\.stdout cannot be closed/.test(err));
3030
console.log('ok');
3131
});
3232
}

test/pseudo-tty/test-stdout-read.in

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello!

test/pseudo-tty/test-stdout-read.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
const common = require('../common');
3+
process.stderr.on('data', common.mustCall(console.log));

test/pseudo-tty/test-stdout-read.out

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<Buffer 48 65 6c 6c 6f 21 0a>

0 commit comments

Comments
 (0)