tty: make _read throw ERR_TTY_WRITABLE_NOT_READABLE

This change avoid an 'read ENOTCONN' error introduced by libuv 1.20.0
when trying to read from a TTY WriteStream. Instead, we are throwing
a more actionable ERR_TTY_WRITABLE_NOT_READABLE.

Fixes: https://github.com/nodejs/node/issues/21203

PR-URL: https://github.com/nodejs/node/pull/21654
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Shingo Inoue <leko.noor@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Matteo Collina 2018-07-03 18:35:59 +02:00
parent 6acb55041b
commit 91eec00ca2
5 changed files with 38 additions and 1 deletions

View File

@ -1694,6 +1694,12 @@ A `Transform` stream finished with data still in the write buffer.
The initialization of a TTY failed due to a system error.
<a id="ERR_TTY_WRITABLE_NOT_READABLE"></a>
### ERR_TTY_WRITABLE_NOT_READABLE
This `Error` is thrown when a read is attempted on a TTY `WriteStream`,
such as `process.stdout.on('data')`.
<a id="ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET"></a>
### ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET

View File

@ -828,6 +828,9 @@ E('ERR_TRANSFORM_ALREADY_TRANSFORMING',
E('ERR_TRANSFORM_WITH_LENGTH_0',
'Calling transform done when writableState.length != 0', Error);
E('ERR_TTY_INIT_FAILED', 'TTY initialization failed', SystemError);
E('ERR_TTY_WRITABLE_NOT_READABLE',
'The Writable side of a TTY is not Readable',
Error);
E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET',
'`process.setupUncaughtExceptionCapture()` was called while a capture ' +
'callback was already active',

View File

@ -25,7 +25,11 @@ const { inherits, _extend } = require('util');
const net = require('net');
const { TTY, isTTY } = process.binding('tty_wrap');
const errors = require('internal/errors');
const { ERR_INVALID_FD, ERR_TTY_INIT_FAILED } = errors.codes;
const {
ERR_INVALID_FD,
ERR_TTY_INIT_FAILED,
ERR_TTY_WRITABLE_NOT_READABLE
} = errors.codes;
const { getColorDepth } = require('internal/tty');
// Lazy loaded for startup performance.
@ -122,6 +126,13 @@ WriteStream.prototype._refreshSize = function() {
}
};
// A WriteStream is not readable from, so _read become a no-op.
// this method could still be called because net.Socket()
// is a duplex
WriteStream.prototype._read = function() {
this.destroy(new ERR_TTY_WRITABLE_NOT_READABLE());
};
// Backwards-compat
WriteStream.prototype.cursorTo = function(x, y) {
if (readline === undefined) readline = require('readline');

View File

@ -0,0 +1,17 @@
'use strict';
const common = require('../common');
const { WriteStream } = require('tty');
const fd = common.getTTYfd();
// Calling resume on a tty.WriteStream should be a no-op
// Ref: https://github.com/nodejs/node/issues/21203
const stream = new WriteStream(fd);
stream.resume();
stream.on('error', common.expectsError({
code: 'ERR_TTY_WRITABLE_NOT_READABLE',
type: Error,
message: 'The Writable side of a TTY is not Readable'
}));