Skip to content

Commit

Permalink
doc: fix up warning text about character devices
Browse files Browse the repository at this point in the history
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: nodejs#21212

PR-URL: nodejs#22569
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
  • Loading branch information
addaleax committed Aug 31, 2018
1 parent a58b8dd commit f2338ed
Showing 1 changed file with 11 additions and 10 deletions.
21 changes: 11 additions & 10 deletions doc/api/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
```

Expand Down

0 comments on commit f2338ed

Please sign in to comment.