-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
process.stdin example from docs no longer works in node 10 #20503
Comments
Bisecting this turned into trisecting, because it seems like we introduced this issue gradually:
@nodejs/streams |
I finally narrowed down the problem I was having with Node 10 and node-pg-query-stream to this and lo and behold someone else had already reported it! What I noticed was that I'd get the first batch of results out of the stream, but then it would abort prematurely without emitting The commit message for 0778f79 looks at odds with the conditional |
I think the idea behind /cc @nodejs/streams @mafintosh |
My commit message there ended up a bit confusing after some back and
fourths in the PR sorry. The intent there in the if to add a generic
conditional of when a readable event is okay to emit (stream not destroyed,
and has data or is ended).
Can someone share a concrete example that is failing now? Then I'll help
take a look.
/m
…On Fri, May 4, 2018, 09:35 Anna Henningsen ***@***.***> wrote:
I think the idea behind (state.length || state.ended) was that we do emit
the readable event both for incoming data, and for the end-of-data
marker. So readable is supposed to be emitted even if the stream has
ended, just not after it has been destroyed.
/cc @nodejs/streams <https://github.com/orgs/nodejs/teams/streams>
@mafintosh <https://github.com/mafintosh>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#20503 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAW_VeW1n2TbpOixo-9h8fs-ZT374Y5_ks5tvATZgaJpZM4Txle2>
.
|
@mafintosh The PR description has a standalone test case, if you want |
@addaleax ah, didn't see that in the email thread but indeed here. |
@mafintosh this might be more involved than you're looking for but the problem I was having is reducible to the "fast-reader" test case in https://github.com/brianc/node-pg-query-stream if you check out that repository and run the tests. |
Any update on that? It breaks some of our tools in development |
I'd like to work on the issue, I seem to have found the underlying cause and hopefully a correct solution =). Will submit a PR soon. |
Avoid trying to emit 'readable' due to the fact that state.length is always >= state.highWaterMark if highWaterMark is 0. Therefore upon .read(0) call (through .on('readable')) stream assumed that it has enough data to emit 'readable' even though state.length === 0 instead of issuing _read(). Which led to the TTY not recognizing that someone is waiting for the input. Fixes: nodejs#20503 Refs: nodejs#18372
Fixed in fe47b8b |
Avoid trying to emit 'readable' due to the fact that state.length is always >= state.highWaterMark if highWaterMark is 0. Therefore upon .read(0) call (through .on('readable')) stream assumed that it has enough data to emit 'readable' even though state.length === 0 instead of issuing _read(). Which led to the TTY not recognizing that someone is waiting for the input. Fixes: #20503 Refs: #18372 PR-URL: #21690 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Opened a documentation PR at #25344. |
Thanks for the prompt follow-up and action on this issue. I have few issues though: After few more tests, here are 2 notables differences between node v9 and v10 (and later): process.stdin.setEncoding('utf8');
process.stdin.on('readable', () => {
console.log("readable");
const chunk = process.stdin.read();
console.log("read");
if (chunk !== null) {
process.stdout.write(`data: ${chunk}`);
}
process.stdin.read(); // <== without this function call the callback is not called and the program exists abruptly
});
process.stdin.on('end', () => {
process.stdout.write('end');
}); 2- in v9 the 'readable' event is fired immediately at program startup even without any user input (and process.stdin.read() returns null in this initial run), in v10 'readable' is not fired immediately at program startup but only upon actual user input (and process.stdin.read() returns the actual input in this initial run) In conclusion I think the example is correct since it works fine on filesystem streams. There may be an issue with how callbacks are activated which would require further attention. |
That’s because it’s arguably more correct – in fact, this should work for all streams since the introduction of streams 3 (i.e. streams with a
I don’t quite understand this question.
I’m not sure, but this could also mean that you’re relying on a peculiarity of filesystem streams? @mcollina One thing I’m wondering, |
The fact that they work is not assured, and it depends on low-level file system timing, the business of the operating system, the type of disk, caches, etc. The while loop is necessary in all cases.
It returns a chunk of data, the chunks are not concatenated. The while loop is necessary to consume all data, and it will trigger a new |
Thanks a lot for this clarification - I believe it would be useful to make this explicit in the Stream documentation (https://nodejs.org/docs/latest-v11.x/api/stream.html#stream_event_readable), and maybe consider updating the example there too. Beyond Stream and Process, a few more documentation pages use "if" instead of "while" and may benefit from an update too: Crypto (https://nodejs.org/api/crypto.html) and Buffer (https://nodejs.org/api/buffer.html)
My understanding now is that the original issue opened by @apieceofbart is caused by a wrong example rather than a node bug. The correct example (with the while loop) works fine for me in v10. So the code injected in fe47b8b is probably fixing another issue. In any case thanks a lot for the help, I am satisfied with the change to "while" in my code so I will not bother you further on this issue. |
The 'readable' event assumes that calls to readable.read() happens within that event handler until readable.read() returns null. Fixes: nodejs#20503
Fixes: #20503 PR-URL: #25344 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
The 'readable' event assumes that calls to readable.read() happens within that event handler until readable.read() returns null. Fixes: #20503 PR-URL: #25375 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Fixes: nodejs#20503 PR-URL: nodejs#25344 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
The 'readable' event assumes that calls to readable.read() happens within that event handler until readable.read() returns null. Fixes: #20503 PR-URL: #25375 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Fixes: nodejs#20503 PR-URL: nodejs#25344 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
The 'readable' event assumes that calls to readable.read() happens within that event handler until readable.read() returns null. Fixes: nodejs#20503 PR-URL: nodejs#25375 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
The docs for this feature still aren't very clear... Has anyone tried piping in a file longer than 65536 bytes via stdin? The example from the docs shows this code: process.stdin.on('readable', () => {
let chunk;
// Use a loop to make sure we read all available data.
while ((chunk = process.stdin.read()) !== null) {
process.stdout.write(`data: ${chunk}`);
}
}); Note the code comment:
Perhaps it's stupid of me, but I assumed this meant the while loop there would cause it to read all of stdin, so I made some code like: process.stdin.on('readable', () => {
let chunk, chunks, content;
chunks = [];
// Use a loop to make sure we read all available data.
while ((chunk = process.stdin.read()) !== null) {
chunks.push(chunk);
}
content = chunks.join('');
console.log(content.length);
render(content);
}); What I see from this naïve code though is that my Unfortunately because the code was trying to So I have to structure the code more like this: var chunk, chunks, content;
chunks = [];
process.stdin.on('end', () => {
content = chunks.join('');
console.error(content.length); // 88106 - yay!
return content;
});
process.stdin.on('readable', function() {
console.error('READABLE')
while ((chunk = process.stdin.read()) !== null) {
chunks.push(chunk);
console.error('CHUNK')
}
}); This makes perfect sense, but I think something of this behaviour ought to be mentioned in the docs. https://nodejs.org/api/process.html#process_process_stdin
and the docs for I understand from the long discussion in the thread above that what the while loop is really for is to ensure that the stream doesn't end early, if there is initially nothing to read? Perhaps this could all be made a bit clearer somehow. |
@anentropic I think a PR to improve the docs would be welcomed! |
@mcollina ok no prob, give me a day or two |
Fixes: #20503 PR-URL: #25344 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
The 'readable' event assumes that calls to readable.read() happens within that event handler until readable.read() returns null. Fixes: #20503 PR-URL: #25375 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Fixes: #20503 PR-URL: #25344 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
The 'readable' event assumes that calls to readable.read() happens within that event handler until readable.read() returns null. Fixes: #20503 PR-URL: #25375 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Fixes: #20503 PR-URL: #25344 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
The 'readable' event assumes that calls to readable.read() happens within that event handler until readable.read() returns null. Fixes: #20503 PR-URL: #25375 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
I am running
process.stdin
example from docs:I expect the same results as in node v9 and below: command line should wait for my input and return it prefixed with
data:
. Instead, process is closed right away. I believe this is regression as example works fine in node v9 and v8.(edited by @addaleax: syntax highlighting)
The text was updated successfully, but these errors were encountered: