diff --git a/doc/api/errors.md b/doc/api/errors.md index 590c504ae68edf..dbc1c0e48b35af 100755 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1172,12 +1172,32 @@ A call was made and the UDP subsystem was not running. ### ERR_STDERR_CLOSE + + An attempt was made to close the `process.stderr` stream. By design, Node.js does not allow `stdout` or `stderr` streams to be closed by user code. ### ERR_STDOUT_CLOSE + + An attempt was made to close the `process.stdout` stream. By design, Node.js does not allow `stdout` or `stderr` streams to be closed by user code. diff --git a/doc/api/process.md b/doc/api/process.md index 8279f596a51fc1..73f6dbda7e332e 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -1703,9 +1703,7 @@ important ways: 1. They are used internally by [`console.log()`][] and [`console.error()`][], respectively. -2. They cannot be closed ([`end()`][] will throw). -3. They will never emit the [`'finish'`][] event. -4. Writes may be synchronous depending on what the stream is connected to +2. Writes may be synchronous depending on what the stream is connected to and whether the system is Windows or POSIX: - Files: *synchronous* on Windows and POSIX - TTYs (Terminals): *asynchronous* on Windows, *synchronous* on POSIX @@ -1925,7 +1923,6 @@ cases: [`'exit'`]: #process_event_exit -[`'finish'`]: stream.html#stream_event_finish [`'message'`]: child_process.html#child_process_event_message [`'rejectionHandled'`]: #process_event_rejectionhandled [`'uncaughtException'`]: #process_event_uncaughtexception @@ -1936,7 +1933,6 @@ cases: [`EventEmitter`]: events.html#events_class_eventemitter [`console.error()`]: console.html#console_console_error_data_args [`console.log()`]: console.html#console_console_log_data_args -[`end()`]: stream.html#stream_writable_end_chunk_encoding_callback [`net.Server`]: net.html#net_class_net_server [`net.Socket`]: net.html#net_class_net_socket [`process.argv`]: #process_process_argv diff --git a/lib/internal/errors.js b/lib/internal/errors.js index e878766f680605..c260b547b8a7e8 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -427,8 +427,6 @@ E('ERR_SOCKET_BUFFER_SIZE', (reason) => `Could not get or set buffer size: ${reason}`); E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data'); E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running'); -E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed'); -E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed'); E('ERR_UNKNOWN_BUILTIN_MODULE', (id) => `No such built-in module: ${id}`); E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s'); E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s'); diff --git a/lib/internal/process/stdio.js b/lib/internal/process/stdio.js index 7faef381f895bf..46641b5871646f 100644 --- a/lib/internal/process/stdio.js +++ b/lib/internal/process/stdio.js @@ -1,9 +1,11 @@ 'use strict'; -const errors = require('internal/errors'); +const errors = require('internal/errors').codes; exports.setup = setupStdio; +function dummyDestroy(err, cb) { cb(err); } + function setupStdio() { var stdin; var stdout; @@ -13,11 +15,8 @@ function setupStdio() { if (stdout) return stdout; stdout = createWritableStdioStream(1); stdout.destroySoon = stdout.destroy; - stdout._destroy = function(er, cb) { - // Avoid errors if we already emitted - er = er || new errors.Error('ERR_STDOUT_CLOSE'); - cb(er); - }; + // Override _destroy so that the fd is never actually closed. + stdout._destroy = dummyDestroy; if (stdout.isTTY) { process.on('SIGWINCH', () => stdout._refreshSize()); } @@ -28,11 +27,8 @@ function setupStdio() { if (stderr) return stderr; stderr = createWritableStdioStream(2); stderr.destroySoon = stderr.destroy; - stderr._destroy = function(er, cb) { - // Avoid errors if we already emitted - er = er || new errors.Error('ERR_STDERR_CLOSE'); - cb(er); - }; + // Override _destroy so that the fd is never actually closed. + stdout._destroy = dummyDestroy; if (stderr.isTTY) { process.on('SIGWINCH', () => stderr._refreshSize()); } diff --git a/test/parallel/test-stdout-cannot-be-closed-child-process-pipe.js b/test/parallel/test-stdout-cannot-be-closed-child-process-pipe.js index d19b522e290ba9..7cd4b90c008a2f 100644 --- a/test/parallel/test-stdout-cannot-be-closed-child-process-pipe.js +++ b/test/parallel/test-stdout-cannot-be-closed-child-process-pipe.js @@ -24,9 +24,9 @@ function parent() { }); child.on('close', function(code, signal) { - assert(code); + assert.strictEqual(code, 0); + assert.strictEqual(err, ''); assert.strictEqual(out, 'foo'); - assert(/process\.stdout cannot be closed/.test(err)); console.log('ok'); }); } diff --git a/test/pseudo-tty/test-stdout-read.in b/test/pseudo-tty/test-stdout-read.in new file mode 100644 index 00000000000000..10ddd6d257e013 --- /dev/null +++ b/test/pseudo-tty/test-stdout-read.in @@ -0,0 +1 @@ +Hello! diff --git a/test/pseudo-tty/test-stdout-read.js b/test/pseudo-tty/test-stdout-read.js new file mode 100644 index 00000000000000..90f017ed77b7be --- /dev/null +++ b/test/pseudo-tty/test-stdout-read.js @@ -0,0 +1,3 @@ +'use strict'; +const common = require('../common'); +process.stderr.on('data', common.mustCall(console.log)); diff --git a/test/pseudo-tty/test-stdout-read.out b/test/pseudo-tty/test-stdout-read.out new file mode 100644 index 00000000000000..3b7fda223d0e6c --- /dev/null +++ b/test/pseudo-tty/test-stdout-read.out @@ -0,0 +1 @@ +