-
Notifications
You must be signed in to change notification settings - Fork 7.3k
child_process: give forks stdout
and stderr
#2454
Conversation
Previously using these streams was not possible because of making them use given file descriptors. This solution is more generic - it uses `pipe` function to pipe fork's output into parent's `stdout` and `stderr` unless `silent: true` is set as an option. This doesn't break any existing API and it makes `fork` more compatible with `spawn`. Please note that fork's `stdout` and `stderr` aren't meant to be used as communication channels - use `fork(...).send()` instead. Fixes #2442.
+1 to exposing @ry Can't we just set |
We do expose them. We just pipe things to var fork = require('child_process').fork,
child = fork('my-cool-script');
child.stdout.on('data', function (chunk) {
console.log('got a data from my cool script', chunk);
}); |
…cesses. Currently blocked by nodejs/node-v0.x-archive#2454
@mmalecki Oh. My mistake. Lets make this happen then. Consistency in node child_process APIs is paramount imho. |
… Basic tests are passing now.
+1 Yes, this change would be very useful! For some projects I need the message channel and don't want the forked child to output to stdout / stderr but to my own logging code in the parent. |
@mmalecki this is exactly what I had in mind. But we need to update the silent testcase after this has landed, since it will now be true in any case. I would like to do it but I just don't have the time. |
@@ -181,6 +177,11 @@ exports.fork = function(modulePath, args, options) { | |||
|
|||
var child = spawn(process.execPath, args, options); | |||
|
|||
if (!options.silent) { | |||
child.stdout.pipe(process.stdout, { end: false }); | |||
child.stderr.pipe(process.stderr, { end: false }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you measured the performance impact?
A direct write to stdout / stderr is one syscall + one (user to kernel space) mempcy. Piping the output means three syscalls + three memcpys and a task switch if the child and parent run on the same CPU.
It could make a considerable difference for applications that print out megabytes of data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't aware of the performance implications, maybe two options is prudent on which pipes stdout and stderr and one which shares them. Sharing them logging a real pain because there is no way to mulitplex the merged log into several files. If you run a lot of worker processes this is important imho
I have made a quick bechmark: https://gist.github.com/1558988 |
Thanks Andreas, I was about to write something like that. Seems like it doesn't hurt performance that much (it's approximately 40 ms slower with pipe). |
@mmalecki My opinion is to make pipe default but also allowing use of
If userland want this very fast they can do: |
…cesses. Currently blocked by nodejs/node-v0.x-archive#2454
we want |
Fundamentally I think this is the wrong decision. They are not threads, they are child processes and many people will want to multiplex their log files accordingly. |
@indexzero except when they aren't processes. There will be options for having pipes for stdio - but it's not going to be default - by default they share stdio. |
@ry @isaacs spent some time explaining this to me in some depth and how isolates is going to change things. There are some real-world cases where you want to spawn a child process with IPC always, as opposed to a new isolate. A good example of this is This is why I'm going to stand-by my complaint of the inconsistency of
var childWithIpc = require('child_process').spawn('some/node-like/thing/like/bin/coffee', 'some/file.js', {
ipc: true
}); Just my $0.02 |
+1 to @indexzero's idea. IMO it'd save people a lot of confusion. |
Starting as a separate process will probably always be the default, unless there is a significant performance win on some platforms.
Coffee-script should port it, and provide a This is highly solveable in userland. |
And already solved: https://github.com/stolsma/node-fork That's not really the point though. Shouldn't we be striving for the best core APIs possible which limit the necessity for such user-land solutions? This API is very fundamental to me, passing the buck (to coffeescript for example) doesn't really do it for me. You know me, I don't use coffeescript; but people use it with forever. This is a problem I've seen in real-world usage. At the very least, all of the internals of setting up the JSON channel should exposed through the child_process module to allow user-land to make these decisions instead of having to copy/paste core code as we had to do in node-fork. |
So, we should all just agree with core API being half-baked and move on to the userland? I don't find this solution optimal. If something is in the core, it should be the best one. I like what @indexzero proposed - we could provide a I'll be very happy to pull request that. So can we please stop nerdfighting and actually move on to code? |
Here's the plan: The option will be
The default for fork will be Closing this pull request. @mmalecki has offered to send a new one. |
Previously using these streams was not possible because of making them
use given file descriptors. This solution is more generic - it uses
pipe
function to pipe fork's output into parent'sstdout
andstderr
unlesssilent: true
is set as an option.This doesn't break any existing API and it makes
fork
more compatiblewith
spawn
.Please note that fork's
stdout
andstderr
aren't meant to be used ascommunication channels - use
fork(...).send()
instead.Fixes #2442.
It'd be awesome to backport it to 0.6, it can be merge easily (I can provide another pull request for that). I find current behavior inconsistent with other APIs (also, documentation doesn't mention it).
/cc @bmeck