-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
stream.pipeline abruptly kill the node process #48406
Comments
You got into Async and Await hell. In function pipeLineStream() you should not use 'await'. Instead use .then() as it is returning promise. like: pipeline(rs, ws).then(()=>{ };` This will work. |
@rohith-bot The standard output seems to be "half" working, but the file
Notice that Additionally, can you explain why some earlier versions of node ( And also, why can't I |
have you tried using a buffer |
@rohith-bot This issue isn't about how to circumvent the problem, as I've already found the viable workaround without the need to use It is about pointing out the valid usecase of |
@nodejs/streams |
Can you make a more minimal sample? |
@ronag From 50 to 18 LoC, only focus on the bug, node import { createWriteStream } from "fs";
import { Readable, promises } from "stream";
const generateContent = async (rs) => {
rs.push("start\n");
for (let i = 0; i < 1024; i++)
rs.push("11bf5b37-e0b8-42e0-8dcf-dc8c4aefc000\n");
rs.push("finished\n");
rs.push(null);
};
const main = async () => {
const [rs, ws] = [new Readable(), createWriteStream("foobar.txt")];
await Promise.all([generateContent(rs), promises.pipeline(rs, ws)]);
console.log("--- program finished successfully");
};
main().catch((e) => console.error("*** ERR:", e)); |
I think this is normal (unfortunately) and expacted. Promises do not keep the event loop alive and I think there is a race condition where there are only promises waiting to be processed. To fix this, you should use ESM and Top-Level Await and await your |
const main = async () => {
await new Promise((resolve) => setTimeout(resolve, 5000));
console.log("finished waiting");
};
main(); But for the sake of conversation and progress, as you suggest, I did change the last line into await main().catch((e) => console.error("*** ERR:", e)); And nothing changed. About the race conditions part, possibly, but certainly not the Promises. Otherwise it would affect all versions of node that support Promise. I re-checked the code again, and it's clearly that I did // ...
await Promise.all([generateContent(rs), promises.pipeline(rs, ws)]);
// ... |
I just ran the sample on |
|
@ronag It affects |
Let me re-phrase the required conditions that this issue affects again, using minimal snippet.
|
Yea, I see the problem. |
Fixes: nodejs#48406 PR-URL: nodejs#48435 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Debadree Chatterjee <debadree333@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Fixes: nodejs#48406 PR-URL: nodejs#48435 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Debadree Chatterjee <debadree333@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Version
v18.16.0
Platform
Linux 6.3.6-zen1-1-zen #1 ZEN SMP PREEMPT_DYNAMIC Mon, 05 Jun 2023 15:12:42 +0000 x86_64 GNU/Linux
Subsystem
stream
What steps will reproduce the bug?
This is the snippet that generate Readable stream by pushing
start
,finished
, and 1024 UUID instances in between, and then using that to pipe to file Writable stream namedfoobar.txt
There are two code paths in this snippet
node pipeline.mjs
will usestream.pipeline(rs,ws)
to stream the filepipelineStream
node pipeline.mjs m
will users.pipe(ws)
+Promise
to stream the filemanuallyPipeStream
How often does it reproduce? Is there a required condition?
I've tested the code against
v16.20.0
,v18.15.0
,v18.16.0
,v20.3.0
, in Arch Linux and macOS 12OSes doesn't seems to be the factor of this problem.
The problem seems to only exist when all of these conditions are met:
v18.16.0
orv20.3.0
node pipeline.mjs
, to usestream.pipeline(rs,ws)
code pathWhat is the expected behavior? Why is that the expected behavior?
When running the code successfully,
foobar.txt
with the size of 37 KiB, with properstart
,finished
and UUIDs in betweenWhat do you see instead?
The node process is abnormally killed without any error/exception thrown and exit code is just
0
File
foobar.txt
become malformed:start
and 443 UUIDs, withoutfinished
16384
Additional information
Regardless of node versions and OSes, running the code using flag:
node pipeline.mjs m
, to users.pipe(ws)
+Promise
code path, do always produce the correct results.Minimal snippet that has one code path, and only focus on the issue
The text was updated successfully, but these errors were encountered: