Skip to content

Commit 09cc780

Browse files
committed
tty: set the handle to blocking mode
Refs: #1771 Refs: #6456 Refs: #6773 Refs: #7743 PR-URL: #6816
1 parent a58b48b commit 09cc780

File tree

4 files changed

+47
-19
lines changed

4 files changed

+47
-19
lines changed

doc/api/cli.md

+11
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,17 @@ Path to the file used to store the persistent REPL history. The default path is
288288
to an empty string (`""` or `" "`) disables persistent REPL history.
289289

290290

291+
### `NODE_TTY_UNSAFE_ASYNC=1`
292+
<!-- YAML
293+
added: REPLACEME
294+
-->
295+
296+
When set to `1`, writes to `stdout` and `stderr` will be non-blocking and
297+
asynchronous when outputting to a TTY on platforms which support async stdio.
298+
Setting this will void any guarantee that stdio will not be interleaved or
299+
dropped at program exit. **Use of this mode is not recommended.**
300+
301+
291302
[Buffer]: buffer.html#buffer_buffer
292303
[debugger]: debugger.html
293304
[REPL]: repl.html

doc/api/process.md

+27-17
Original file line numberDiff line numberDiff line change
@@ -858,10 +858,9 @@ if (someConditionNotMet()) {
858858
```
859859

860860
The reason this is problematic is because writes to `process.stdout` in Node.js
861-
are usually *non-blocking* and may occur over multiple ticks of the Node.js
862-
event loop.
863-
Calling `process.exit()`, however, forces the process to exit *before* those
864-
additional writes to `stdout` can be performed.
861+
are sometimes *non-blocking* and may occur over multiple ticks of the Node.js
862+
event loop. Calling `process.exit()`, however, forces the process to exit
863+
*before* those additional writes to `stdout` can be performed.
865864

866865
Rather than calling `process.exit()` directly, the code *should* set the
867866
`process.exitCode` and allow the process to exit naturally by avoiding
@@ -1429,15 +1428,20 @@ Android)
14291428
The `process.stderr` property returns a [Writable][] stream equivalent to or
14301429
associated with `stderr` (fd `2`).
14311430

1432-
`process.stderr` and `process.stdout` are unlike other streams in Node.js in
1433-
that they cannot be closed (calling [`end()`][] will throw an Error), they never
1434-
emit the [`'finish'`][] event, and writes can block when output is redirected to
1435-
a file (although disks are fast and operating systems normally employ write-back
1436-
caching so it should be a very rare occurrence indeed.)
1431+
Note: `process.stderr` and `process.stdout` differ from other Node.js streams
1432+
in several ways:
1433+
1. They cannot be closed ([`end()`][] will throw).
1434+
2. They never emit the [`'finish'`][] event.
1435+
3. Writes _can_ block when output is redirected to a file.
1436+
- Note that disks are fast and operating systems normally employ write-back
1437+
caching so this is very uncommon.
1438+
4. Writes on UNIX __will__ block by default if output is going to a TTY
1439+
(a terminal).
1440+
5. Windows functionality differs. Writes block except when output is going to a
1441+
TTY.
14371442

1438-
Additionally, `process.stderr` and `process.stdout` are blocking when outputting
1439-
to TTYs (terminals) on OS X as a workaround for the OS's very small, 1kb
1440-
buffer size. This is to prevent interleaving between `stdout` and `stderr`.
1443+
To check if Node.js is being run in a TTY context, read the `isTTY` property
1444+
on `process.stderr`, `process.stdout`, or `process.stdin`:
14411445

14421446
## process.stdin
14431447

@@ -1482,11 +1486,17 @@ console.log = (msg) => {
14821486
};
14831487
```
14841488

1485-
`process.stderr` and `process.stdout` are unlike other streams in Node.js in
1486-
that they cannot be closed (calling [`end()`][] will throw an Error), they never
1487-
emit the [`'finish'`][] event and that writes can block when output is
1488-
redirected to a file (although disks are fast and operating systems normally
1489-
employ write-back caching so it should be a very rare occurrence indeed.)
1489+
Note: `process.stderr` and `process.stdout` differ from other Node.js streams
1490+
in several ways:
1491+
1. They cannot be closed ([`end()`][] will throw).
1492+
2. They never emit the [`'finish'`][] event.
1493+
3. Writes _can_ block when output is redirected to a file.
1494+
- Note that disks are fast and operating systems normally employ write-back
1495+
caching so this is very uncommon.
1496+
4. Writes on UNIX __will__ block by default if output is going to a TTY
1497+
(a terminal).
1498+
5. Windows functionality differs. Writes block except when output is going to a
1499+
TTY.
14901500

14911501
To check if Node.js is being run in a TTY context, read the `isTTY` property
14921502
on `process.stderr`, `process.stdout`, or `process.stdin`:

doc/node.1

+7
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,13 @@ Path to the file used to store the persistent REPL history. The default path
169169
is ~/.node_repl_history, which is overridden by this variable. Setting the
170170
value to an empty string ("" or " ") disables persistent REPL history.
171171

172+
.TP
173+
.BR NODE_TTY_UNSAFE_ASYNC=1
174+
When set to 1, writes to stdout and stderr will be non-blocking and asynchronous
175+
when outputting to a TTY on platforms which support async stdio.
176+
Setting this will void any guarantee that stdio will not be interleaved or
177+
dropped at program exit. \fBAvoid use.\fR
178+
172179

173180
.SH RESOURCES AND DOCUMENTATION
174181

lib/tty.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ function WriteStream(fd) {
4848
writable: true
4949
});
5050

51-
// Prevents interleaved stdout/stderr output in OS X terminals.
51+
// Prevents interleaved or dropped stdout/stderr output for terminals.
5252
// As noted in the following reference, local TTYs tend to be quite fast and
5353
// this behaviour has become expected due historical functionality on OS X,
5454
// even though it was originally intended to change in v1.0.2 (Libuv 1.2.1).
5555
// Ref: https://github.com/nodejs/node/pull/1771#issuecomment-119351671
56-
if (process.platform === 'darwin') this._handle.setBlocking(true);
56+
this._handle.setBlocking(process.env.NODE_TTY_UNSAFE_ASYNC !== '1');
5757

5858
var winSize = [];
5959
var err = this._handle.getWindowSize(winSize);

0 commit comments

Comments
 (0)