Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: warn against streaming from character devices #21212

Conversation

gireeshpunathil
Copy link
Member

charcter device streaming works just like any other streams, but hangs
on the close callsite due to the worker thread being blocked on the read
and main thread waiting for any async event that may not occur.

Document this behavior and suggest a potential workaround.

Fixes: #15439

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added doc Issues and PRs related to the documentations. fs Issues and PRs related to the fs subsystem / file system. labels Jun 8, 2018
@jasnell jasnell requested a review from mafintosh June 9, 2018 01:00
doc/api/fs.md Outdated
@@ -1381,6 +1381,12 @@ the specified file descriptor. This means that no `'open'` event will be
emitted. Note that `fd` should be blocking; non-blocking `fd`s should be passed
to [`net.Socket`][].

Also note that the blocking fd, if pointing to a character device (such as
keyboard or sound card) that are end-less streams and do not produce EOF
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: end-less -> endless

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, ptal

@Trott
Copy link
Member

Trott commented Jun 9, 2018

@nodejs/fs @nodejs/documentation

doc/api/fs.md Outdated
@@ -1381,6 +1381,12 @@ the specified file descriptor. This means that no `'open'` event will be
emitted. Note that `fd` should be blocking; non-blocking `fd`s should be passed
to [`net.Socket`][].

Also note that the blocking fd, if pointing to a character device (such as

This comment was marked as resolved.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vsemozhetbyt - split it for more clarity, ptal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"fd" should be in backticks, I think. (Can go either way, but for consistency with the previous paragraph, for example.)

You can probably drop Also note that.

Trott
Trott previously requested changes Jun 10, 2018
Copy link
Member

@Trott Trott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just putting a 'request changes' here to make sure this doesn't land without @vsemozhetbyt's comment being addressed. If the comment gets addressed, feel free to dismiss this review.

Copy link
Contributor

@vsemozhetbyt vsemozhetbyt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With nits)

doc/api/fs.md Outdated
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 epitomize endless streams. As a result, they do not
respond to stream.close() call. A workaround is to close the stream first using
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stream.close() -> `stream.close()`?

doc/api/fs.md Outdated
This is because these devices do not produce EOF character as part of their data
flow cycle, and thereby epitomize endless streams. As a result, they do not
respond to stream.close() call. A workaround is to close the stream first using
stream.close() and then push a random character into the stream. This unblocks
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stream.close() -> `stream.close()`?

@gireeshpunathil
Copy link
Member Author

@vsemozhetbyt - thanks, nits addressed.

doc/api/fs.md Outdated
Also note that 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 epitomize endless streams. As a result, they do not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think "epitomize" is a word most non-english speakers will know.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please suggest alternative, if you know.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just endless streams straight up? i don't personally know what epitomize mean

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed the wording from epitomize to exemplifies

doc/api/fs.md Outdated
respond to `stream.close()` call. A workaround is to close the stream first
using `stream.close()` and then push a random character into the stream.
This unblocks the reader thread, leads to the completion of the data flow cycle,
and the actual closing of the stream.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow this last sentence.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the problem with character device when abstracted as streams in Node is that they operate on a blocking file descriptor, managed by pooled worker threads, with a passback async handle to the main thread. so once they engage in reading, there is no way to unblock the thread, other than passing a dummy character to 'unblock' the reader thread, close the libuv handles and disengage from further reading.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that something you can do with the fs api here? An example might work to reduce confusion :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added an example

doc/api/fs.md Outdated

```js
const fs = require('fs');
// create a stream from some character device
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: it seems we usually start comments with an uppercase letter and end them with a period.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, done.

@gireeshpunathil gireeshpunathil dismissed Trott’s stale review June 22, 2018 10:33

reason for this change request was addressed, hence dismissing

@gireeshpunathil
Copy link
Member Author

@mafintosh @Trott - all comments were addressed, PTAL. thanks.

@jasnell
Copy link
Member

jasnell commented Aug 12, 2018

ping @mafintosh @Trott

doc/api/fs.md Outdated
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()` call. A workaround is to close the stream first
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omit call?

doc/api/fs.md Outdated
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()` call. A workaround is to close the stream first
using `stream.close()` and then push a random character into the stream, issue
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue -> and issue or issuing?

@Trott
Copy link
Member

Trott commented Aug 13, 2018

Left some non-blocking nits. I'm fine with this landing, but am not leaving an approval because the behavior described is not something I'm familiar with. I trust that it is being accurately described, though.

charcter device streaming works just like any other streams, but hangs
on the close callsite due to the worker thread being blocked on the read
and main thread waiting for any async event that may not occur.

Document this behavior and suggest a potential workaround.

Fixes: nodejs#15439
@gireeshpunathil
Copy link
Member Author

thanks @Trott , I have addressed all your comments.

@gireeshpunathil
Copy link
Member Author

landed as 66e6d78

gireeshpunathil added a commit that referenced this pull request Aug 28, 2018
charcter device streaming works just like any other streams, but hangs
on the close callsite due to the worker thread being blocked on the read
and main thread waiting for any async event that may not occur.

Document this behavior and suggest a potential workaround.

Fixes: #15439
PR-URL: #21212

Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
addaleax added a commit to addaleax/node that referenced this pull request Aug 28, 2018
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
addaleax pushed a commit that referenced this pull request Aug 28, 2018
charcter device streaming works just like any other streams, but hangs
on the close callsite due to the worker thread being blocked on the read
and main thread waiting for any async event that may not occur.

Document this behavior and suggest a potential workaround.

Fixes: #15439
PR-URL: #21212

Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
addaleax added a commit that referenced this pull request Aug 31, 2018
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: #21212

PR-URL: #22569
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
addaleax added a commit that referenced this pull request Aug 31, 2018
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: #21212

PR-URL: #22569
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
targos pushed a commit that referenced this pull request Sep 3, 2018
charcter device streaming works just like any other streams, but hangs
on the close callsite due to the worker thread being blocked on the read
and main thread waiting for any async event that may not occur.

Document this behavior and suggest a potential workaround.

Fixes: #15439
PR-URL: #21212

Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
targos pushed a commit that referenced this pull request Sep 3, 2018
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: #21212

PR-URL: #22569
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
targos pushed a commit that referenced this pull request Sep 6, 2018
charcter device streaming works just like any other streams, but hangs
on the close callsite due to the worker thread being blocked on the read
and main thread waiting for any async event that may not occur.

Document this behavior and suggest a potential workaround.

Fixes: #15439
PR-URL: #21212

Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
targos pushed a commit that referenced this pull request Sep 6, 2018
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: #21212

PR-URL: #22569
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc Issues and PRs related to the documentations. fs Issues and PRs related to the fs subsystem / file system.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot properly close/cleanup character device ReadStream (process hangs)
7 participants