-
Notifications
You must be signed in to change notification settings - Fork 30.6k
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
Add the ability to wire-up listeners before starting a child process #38081
Comments
If I'm understanding you correctly, there's no problem here. I think you might need to take some time to understand the event loop. In this code that you provide, the listeners are wired up before the child process is able to emit any events
This will always exhibit the expected behavior because "data" events cannot fire until the current tick in the event loop is done. So both listeners will always receive the same events. No On the other hand:
Given this code, I would not expect |
At least in the sample code you provide, there is no window. No need to hope for the best. Even this works as expected:
I'm going to go ahead and close this, but feel free to comment or re-open if I've misunderstood the issue here. Thanks for requesting a feature! |
So you're saying the user should trust that events registered will not be fired until there's a context switch. Alright, if that's so inherent in nodejs programming then you're right, the edge case I described is not inherently a problem. And still, I can't seem to shake the feeling that just spawning a process to the air without allowing any prior wireup is a bad idea. This is just my hunch, I have no concrete examples here. What do you think? |
Yes, because if not, then the event loop is broken and nothing will work the way it is supposed to. This is similar to the way the user also needs to trust that the first line of the file is parsed and executed before the second line. That analogy is an exaggeration, but much less of one than one might think.
Like this? Still works as expected.
I don't believe that is correct. https://stackoverflow.com/a/35464318/436641 |
Since your example didn't quite stress the default const { exec } = require("child_process");
p = exec("seq 100000", { maxBuffer: 100 }); // large output, too small of a buffer
arr = [];
console.log("starting loop");
for (let i = 0; i < 99999999; i++) {
arr.push(Math.random(i));
}
console.log("ending loop");
p.stdout.on("data", (d) => console.log(d)); But surprisingly, the buffer limit simply didn't kick in. The docs say (regarding
But in reality, setting a low So.. now I'm just confused. |
I imagine it's working because Anyway, @TheYarin, this will get the truncated const { exec } = require("child_process");
p = exec("seq 100000", { maxBuffer: 100 }, (err, stdout, stderr) => {
console.log('ERR', err);
console.log('STDOUT', stdout);
console.log('STDERR', stderr);
}); Adding in the long const { exec } = require("child_process");
p = exec("seq 100000", { maxBuffer: 100 }, (err, stdout, stderr) => {
console.log('ERR', err);
console.log('STDOUT', stdout);
console.log('STDERR', stderr);
});
// Blocks the event loop but doesn't change the ultimate result of the command above.
arr = [];
console.log("starting loop");
for (let i = 0; i < 99999999; i++) {
arr.push(Math.random(i));
}
console.log("ending loop"); |
Is your feature request related to a problem? Please describe.
When registering multiple listeners (callbacks) to the
data
event of a child process'sstdout
, there's no way to get the child process to wait for all the callbacks to be registered before starting. This means there's a window between registering the first listener and the second one in which the first listener might "pull" the first available chunk and when the second listener is registered, it won't receive the first chunk.A thinned-down example:
From what I understand from reading the documentation of child_process, when a child process is started nodejs saves it's output in a buffer until a listener is registered (either by directly binding to the 'data' event or by
pipe()
ing stdout to a writable stream). This behaviour creates two potential problems:Describe the solution you'd like
The solution I propose is to allow wiring up all the listeners and pipes before starting the child process.
Considering backwards compatibility, I imagine the best way to achieve this is by passing a new option (something like
autostart
that will default totrue
) to the options parameter ofspawn
,exec
etc., that will make those functions return aChildProcess
instance that was not yet started, together with a newstart()
method added to theChildProcess
class.Describe alternatives you've considered
The alternatives as I see them are:
The text was updated successfully, but these errors were encountered: