You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Apr 22, 2023. It is now read-only.
Repository navigation
This repository was archived by the owner on Apr 22, 2023. It is now read-only.
Currently process.stdin / stdout / stderr is blocking, except when it is a pipe on windows. Weird and surprising. Very unpractical in cases where stdio is used as an IPC mechanism between node processes.
I've experienced a similar issue with stdio in Windows, and have somewhat worked around it in the meantime with this horrible, horrible hack.
While my mini exit lib works well in place of process.exit in some cases, it completely fails to help in this case:
varexitHack=require('./exit').exit;// If there are pending stdout / stderr writes when "condition" is met...if(condition){exitHack();}// ...this code will still do something. Whoops!doSomething();
I haven't seen this problem in OS X or Linux. It would be great if Node.js behaved the same cross-OS.
I have started to look into this issue. Here is what I have found so far.
If stdout is not piped, then the output goes through libuv tty code which is blocking as expected.
If stdout is piped, the output goes through libuv pipe code.
The pipe code checks to see if the pipe supports overlapped IO.
In the case of piped stdout it does not - NtQueryInformationFile returns a mode of FILE_SYNCHRONOUS_IO_NONALERT, which means:
All operations on the file are performed synchronously.
Wait requests in the system that must synchronize I/O queuing and completion are not subject to alerts
In this case the pipe code uses the thread pool to perform all IO.
So when the process exits, the write requests are queued up for the thread pool to execute, but they are never executed.
I made a quick hack to simply let the Write operations execute synchronously when the pipe is in this mode.
In the tests that I have, this fixes the problem of data being lost when the process exits.
This approach means that stdout would have blocking IO behavior even when piped, without requiring any new API.
Other pipes that have mode FILE_SYNCHRONOUS_IO_NONALERT or FILE_SYNCHRONOUS_IO_ALERT would also end up being blocking.
These modes may be set on a pipe or file when creating it, but libuv never sets it.
Does this seem like an acceptable way of fixing this issue?
Excellent! Any chance of getting this into node 0.10.x? This fix will allow me to get rid of ugly workarounds I need to use currently to not loose process output.
Updated the proposed fix. Added API uv_pipe_setblocking() to libuv and changed windows pipe to use synchronous writes if this is set. Updated node code to call uv_pipe_setblocking() for stdio over pipe.
Activity
cowboy commentedon Aug 26, 2012
I've experienced a similar issue with stdio in Windows, and have somewhat worked around it in the meantime with this horrible, horrible hack.
While my mini
exitlib works well in place ofprocess.exitin some cases, it completely fails to help in this case:I haven't seen this problem in OS X or Linux. It would be great if Node.js behaved the same cross-OS.
bpasero commentedon Jan 17, 2013
Any update? Will this land in 0.10?
isaacs commentedon Mar 6, 2013
This issue has been stagnant for months. In order for this to happen, it will need a champion.
Are you that champion? Would you like to see stdio have a more consistently blocking/nonblocking interface, which works the same on Windows and Unix?
Heed the call. Build the bits that need to go into libuv. Sketch out an API in node for it.
It seems that it won't make the 0.10 cut-off, I'm afraid. Maybe next pass.
HenryRawas commentedon May 24, 2013
I have started to look into this issue. Here is what I have found so far.
If stdout is not piped, then the output goes through libuv tty code which is blocking as expected.
If stdout is piped, the output goes through libuv pipe code.
The pipe code checks to see if the pipe supports overlapped IO.
In the case of piped stdout it does not - NtQueryInformationFile returns a mode of FILE_SYNCHRONOUS_IO_NONALERT, which means:
All operations on the file are performed synchronously.
Wait requests in the system that must synchronize I/O queuing and completion are not subject to alerts
In this case the pipe code uses the thread pool to perform all IO.
So when the process exits, the write requests are queued up for the thread pool to execute, but they are never executed.
I made a quick hack to simply let the Write operations execute synchronously when the pipe is in this mode.
In the tests that I have, this fixes the problem of data being lost when the process exits.
This approach means that stdout would have blocking IO behavior even when piped, without requiring any new API.
Other pipes that have mode FILE_SYNCHRONOUS_IO_NONALERT or FILE_SYNCHRONOUS_IO_ALERT would also end up being blocking.
These modes may be set on a pipe or file when creating it, but libuv never sets it.
Does this seem like an acceptable way of fixing this issue?
bpasero commentedon May 29, 2013
Excellent! Any chance of getting this into node 0.10.x? This fix will allow me to get rid of ugly workarounds I need to use currently to not loose process output.
bnoordhuis commentedon May 29, 2013
@piscisaureus and/or @sblom: request for comment, please.
HenryRawas commentedon May 29, 2013
Second pull request fixes commit message problems.
sblom commentedon May 30, 2013
@HenryRawas works with me. I'll look at thiS.
HenryRawas commentedon Jun 10, 2013
Updated the proposed fix. Added API uv_pipe_setblocking() to libuv and changed windows pipe to use synchronous writes if this is set. Updated node code to call uv_pipe_setblocking() for stdio over pipe.
bpasero commentedon Jun 14, 2013
@HenryRawas is it realistic to get this fix in for 0.10.x?
HenryRawas commentedon Jun 14, 2013
I am still trying to get the change accepted. I don’t know where it will land.
From: Benjamin Pasero [mailto:[email protected]]
Sent: Friday, June 14, 2013 2:07 AM
To: joyent/node
Cc: Henry Rawas
Subject: Re: [node] Fix blocking / non-blocking stdio woes (#3584)
@HenryRawashttps://github.com/HenryRawas is it realistic to get this fix in for 0.10.x?
—
Reply to this email directly or view it on GitHubhttps://github.com//issues/3584#issuecomment-19446612.
jdalton commentedon Jun 27, 2013
Just wanted to 👍 this issue. Was just bit by it in Windows 8 with Node v0.10.12. I'm still looking for a workaround atm.
dcherman commentedon Jun 27, 2013
@jdalton Did you try the pipe to file workaround?
jdalton commentedon Jun 27, 2013
@dcherman No I haven't. Did I miss it already covered?
Here is what I'm trying to do. I noticed that the stdout
outputwas truncated:cowboy commentedon Jun 27, 2013
No matter what, don't do string concat like that. Use
Bufferinstances and.concatthem.33 remaining items
Workaround for nodejs/node-v0.x-archive#3584.
Workaround for nodejs/node-v0.x-archive#3584.
Avoid node.js 0.10.x exit code bug for MS Windows
cli: replace calls to process.exit with exit as Windows workaround for …
Use exit on Windows to ensure stdio is flushed
Flush buffer on `process.exit` in Windows
Use exit module instead of process.exit for Windows workaround
bug: Fix for Windows' drain error on process.exit (Issue 3584)
Add error-handling for rj-build gulp task.
pgilad commentedon May 26, 2015
Hi, is this considered resolved? Is the use of https://github.com/cowboy/node-exit still recommended for some versions of node?
orangemocha commentedon May 26, 2015
Yes, it is resolved. It was fixed with 20176a9.
You shouldn't need the workaround anymore.
pgilad commentedon May 26, 2015
Great, thanks!
gigapromoters commentedon Jun 1, 2015
Issue still exists for me in 0.12.4, Windows 8.1:
var child = require('child_process').spawn('php',
['-S', 'localhost:8007']);
child.stdout.on('data', function(data) {
console.log("child: "+data.toString());
});
Not sure if this is a bug, but if the process is infinite - then the child.stdout's callback is never triggered.
gigapromoters commentedon Jun 1, 2015
I wrapped php process in another child script, now it works fine.