doc: fix up warning text about character devices

The text contained a number of inaccuracies:

- The main thread is never blocked by a stream close.
- There is no such thing as an EOF character on the OS level,
  the libuv level, or the Node.js stream level.
- These streams *do* respond to `.close()`, but pending
  reads can delay this indefinitely.
- Pushing a random character into the stream works only when
  the source data can be controlled; Using the JS `.push()`
  method is something different, and does not “unblock” any threads.

Refs: https://github.com/nodejs/node/pull/21212

PR-URL: https://github.com/nodejs/node/pull/22569
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
Anna Henningsen 2018-08-28 15:56:30 +02:00
parent a58b8dd545
commit f2338ed195
No known key found for this signature in database
GPG Key ID: 9C63F3A6CD2AD8F9

View File

@ -1454,23 +1454,24 @@ the specified file descriptor. This means that no `'open'` event will be
emitted. `fd` should be blocking; non-blocking `fd`s should be passed to
[`net.Socket`][].
The blocking `fd`, if pointing to a character device (such as keyboard or
sound card) can potentially block the main thread on stream close. This is
because these devices do not produce EOF character as part of their data
flow cycle, and thereby exemplify endless streams. As a result, they do not
respond to `stream.close()`. A workaround is to close the stream first
using `stream.close()` and then push a random character into the stream, and
issue a single read. This unblocks the reader thread, leads to the completion
of the data flow cycle, and the actual closing of the stream.
If `fd` points to a character device that only supports blocking reads
(such as keyboard or sound card), read operations do not finish until data is
available. This can prevent the process from exiting and the stream from
closing naturally.
```js
const fs = require('fs');
// Create a stream from some character device.
const stream = fs.createReadStream('/dev/input/event0');
setTimeout(() => {
stream.close(); // This does not close the stream.
stream.close(); // This may not close the stream.
// Artificially marking end-of-stream, as if the underlying resource had
// indicated end-of-file by itself, allows the stream to close.
// This does not cancel pending read operations, and if there is such an
// operation, the process may still not be able to exit successfully
// until it finishes.
stream.push(null);
stream.read(0); // Pushing a null and reading leads to close.
stream.read(0);
}, 100);
```