Skip to content

Commit e413ef3

Browse files
Fishrock123Myles Borins
authored and
Myles Borins
committed
tty: use blocking mode on OS X
OS X has a tiny 1kb hard-coded buffer size for stdout / stderr to TTYs (terminals). Output larger than that causes chunking, which ends up having some (very small but existent) delay past the first chunk. That causes two problems: 1. When output is written to stdout and stderr at similar times, the two can become mixed together (interleaved). This is especially problematic when using control characters, such as \r. With interleaving, chunked output will often have lines or characters erased unintentionally, or in the wrong spots, leading to broken output. CLI apps often extensively use such characters for things such as progress bars. 2. Output can be lost if the process is exited before chunked writes are finished flushing. This usually happens in applications that use `process.exit()`, which isn't infrequent. See #6980 for more info. This became an issue as result of the Libuv 1.9.0 upgrade. A fix to an unrelated issue broke a hack previously required for the OS X implementation. This resulted in an unexpected behavior change in node. The 1.9.0 upgrade was done in c3cec1e, which was included in v6.0.0. Full details of the Libuv issue that induced this are at #6456 (comment) Refs: #1771 Refs: #6456 Refs: #6773 Refs: #6816 PR-URL: #6895 Reviewed-By: Rod Vagg <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent 2d93202 commit e413ef3

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

doc/api/console.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,15 @@ duplicate the browser's functionality exactly.
5353

5454
## Asynchronous vs Synchronous Consoles
5555

56-
The console functions are asynchronous unless the destination is a file.
56+
The console functions are usually asynchronous unless the destination is a file.
5757
Disks are fast and operating systems normally employ write-back caching;
5858
it should be a very rare occurrence indeed that a write blocks, but it
5959
is possible.
6060

61+
Additionally, console functions are blocking when outputting to TTYs
62+
(terminals) on OS X as a workaround for the OS's very small, 1kb buffer size.
63+
This is to prevent interleaving between `stdout` and `stderr`.
64+
6165
## Class: Console
6266

6367
<!--type=class-->

doc/api/process.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,10 @@ event and that writes can block when output is redirected to a file (although
957957
disks are fast and operating systems normally employ write-back caching so it
958958
should be a very rare occurrence indeed.)
959959

960+
Additionally, `process.stderr` and `process.stdout` are blocking when outputting
961+
to TTYs (terminals) on OS X as a workaround for the OS's very small, 1kb
962+
buffer size. This is to prevent interleaving between `stdout` and `stderr`.
963+
960964
## process.stdin
961965

962966
A `Readable Stream` for stdin (on fd `0`).
@@ -1007,6 +1011,10 @@ event and that writes can block when output is redirected to a file (although
10071011
disks are fast and operating systems normally employ write-back caching so it
10081012
should be a very rare occurrence indeed.)
10091013

1014+
Additionally, `process.stderr` and `process.stdout` are blocking when outputting
1015+
to TTYs (terminals) on OS X as a workaround for the OS's very small, 1kb
1016+
buffer size. This is to prevent interleaving between `stdout` and `stderr`.
1017+
10101018
To check if Node.js is being run in a TTY context, read the `isTTY` property
10111019
on `process.stderr`, `process.stdout`, or `process.stdin`:
10121020

@@ -1102,4 +1110,4 @@ Will print something like:
11021110
[Signal Events]: #process_signal_events
11031111
[Stream compatibility]: stream.html#stream_compatibility_with_older_node_js_versions
11041112
[the tty docs]: tty.html#tty_tty
1105-
[`JSON.stringify()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
1113+
[`JSON.stringify()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

lib/tty.js

+7
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ function WriteStream(fd) {
5959
writable: true
6060
});
6161

62+
// Prevents interleaved stdout/stderr output in OS X terminals.
63+
// As noted in the following reference, local TTYs tend to be quite fast and
64+
// this behaviour has become expected due historical functionality on OS X,
65+
// even though it was originally intended to change in v1.0.2 (Libuv 1.2.1).
66+
// Ref: https://github.com/nodejs/node/pull/1771#issuecomment-119351671
67+
if (process.platform === 'darwin') this._handle.setBlocking(true);
68+
6269
var winSize = [];
6370
var err = this._handle.getWindowSize(winSize);
6471
if (!err) {

0 commit comments

Comments
 (0)