Skip to content

Commit fdac9bd

Browse files
committed
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: nodejs#21203
1 parent 2d32a7e commit fdac9bd

File tree

5 files changed

+38
-1
lines changed

5 files changed

+38
-1
lines changed

doc/api/errors.md

+6
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,12 @@ A `Transform` stream finished with data still in the write buffer.
16841684

16851685
The initialization of a TTY failed due to a system error.
16861686

1687+
<a id="ERR_TTY_WRITABLE_NOT_READABLE"></a>
1688+
### ERR_TTY_WRITABLE_NOT_READABLE
1689+
1690+
This `Error` is thrown when a read is attempted on a TTY `WriteStream`,
1691+
such as `process.stdout.on('data')`.
1692+
16871693
<a id="ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET"></a>
16881694
### ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET
16891695

lib/internal/errors.js

+3
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,9 @@ E('ERR_TRANSFORM_ALREADY_TRANSFORMING',
825825
E('ERR_TRANSFORM_WITH_LENGTH_0',
826826
'Calling transform done when writableState.length != 0', Error);
827827
E('ERR_TTY_INIT_FAILED', 'TTY initialization failed', SystemError);
828+
E('ERR_TTY_WRITABLE_NOT_READABLE',
829+
'The Writable side of a TTY is not Readable',
830+
Error);
828831
E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET',
829832
'`process.setupUncaughtExceptionCapture()` was called while a capture ' +
830833
'callback was already active',

lib/tty.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ const { inherits, _extend } = require('util');
2525
const net = require('net');
2626
const { TTY, isTTY } = process.binding('tty_wrap');
2727
const errors = require('internal/errors');
28-
const { ERR_INVALID_FD, ERR_TTY_INIT_FAILED } = errors.codes;
28+
const {
29+
ERR_INVALID_FD,
30+
ERR_TTY_INIT_FAILED,
31+
ERR_TTY_WRITABLE_NOT_READABLE
32+
} = errors.codes;
2933
const { getColorDepth } = require('internal/tty');
3034

3135
// Lazy loaded for startup performance.
@@ -122,6 +126,13 @@ WriteStream.prototype._refreshSize = function() {
122126
}
123127
};
124128

129+
// A WriteStream is not readable from, so _read become a no-op.
130+
// this method could still be called because net.Socket()
131+
// is a duplex
132+
WriteStream.prototype._read = function() {
133+
this.destroy(new ERR_TTY_WRITABLE_NOT_READABLE());
134+
};
135+
125136
// Backwards-compat
126137
WriteStream.prototype.cursorTo = function(x, y) {
127138
if (readline === undefined) readline = require('readline');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const { WriteStream } = require('tty');
5+
const fd = common.getTTYfd();
6+
7+
// Calling resume on a tty.WriteStream should be a no-op
8+
// Ref: https://github.com/nodejs/node/issues/21203
9+
10+
const stream = new WriteStream(fd);
11+
stream.resume();
12+
13+
stream.on('error', common.expectsError({
14+
code: 'ERR_TTY_WRITABLE_NOT_READABLE',
15+
type: Error,
16+
message: 'The Writable side of a TTY is not Readable'
17+
}));

test/pseudo-tty/test-tty-write-stream-resume-crash.out

Whitespace-only changes.

0 commit comments

Comments
 (0)