Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Fix blocking / non-blocking stdio woes #3584

Closed
piscisaureus opened this issue Jun 29, 2012 · 49 comments · Fixed by ember-cli/ember-cli#3517
Closed

Fix blocking / non-blocking stdio woes #3584

piscisaureus opened this issue Jun 29, 2012 · 49 comments · Fixed by ember-cli/ember-cli#3517

Comments

@piscisaureus
Copy link

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.

Discussion:http://logs.nodejs.org/libuv/2012-06-29#00:40:38.256

Preliminary results: have process.stdout.setBlocking(true|false) or process.stdout.writeSync.

Feel free to post thoughts here.

@cowboy
Copy link

cowboy commented 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 exit lib works well in place of process.exit in some cases, it completely fails to help in this case:

var exitHack = 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.

@bpasero
Copy link

bpasero commented Jan 17, 2013

Any update? Will this land in 0.10?

@isaacs
Copy link

isaacs commented 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
Copy link

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
Copy link

bpasero commented 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
Copy link
Member

@piscisaureus and/or @sblom: request for comment, please.

@HenryRawas
Copy link

Second pull request fixes commit message problems.

@sblom
Copy link

sblom commented May 30, 2013

@HenryRawas works with me. I'll look at thiS.

@HenryRawas
Copy link

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
Copy link

bpasero commented Jun 14, 2013

@HenryRawas is it realistic to get this fix in for 0.10.x?

@HenryRawas
Copy link

I am still trying to get the change accepted. I don’t know where it will land.

From: Benjamin Pasero [mailto:notifications@github.com]
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
Copy link
Member

jdalton commented 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
Copy link

@jdalton Did you try the pipe to file workaround?

@jdalton
Copy link
Member

jdalton commented 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 output was truncated:

var foo = cp.spawn(fooPath, fooOptions);

var output = '';
foo.stdout.on('data', function(data) {
  output += data;
});

foo.on('exit', function() {
  fs.writeFileSync(outputPath, output, 'utf8');
});

@cowboy
Copy link

cowboy commented Jun 27, 2013

No matter what, don't do string concat like that. Use Buffer instances and .concat them.

@jdalton
Copy link
Member

jdalton commented Jun 27, 2013

@dcherman Woo doing:

var logStream = fs.createWriteStream(outputPath);
foo.stdout.pipe(logStream);
foo.on('exit', function() {
  // do some cleanup
});

seems to work :)

@jdalton
Copy link
Member

jdalton commented Jun 28, 2013

Actually nix my issue. I tried it manually via the console and for some reason > isn't capturing all the stdout that's normally being displayed to the console. Looks like it's not a node issue.

sonicdoe added a commit to sonicdoe/brave-mouse that referenced this issue Jan 31, 2015
avital added a commit to meteor/meteor that referenced this issue Feb 2, 2015
This works around a bug that's present in Node
0.8 and 0.10. This will likely be fixed in 0.12.
nodejs/node-v0.x-archive#3584
amavisca pushed a commit to jasmine/jasmine-npm that referenced this issue Feb 4, 2015
- process.exit isn't properly waiting for buffers to finish writing in Windows
- issue in node fixed in v0.11.12: nodejs/node-v0.x-archive#3584

Fixes #20
agebert added a commit to e2ebridge/e2e-conf that referenced this issue Feb 6, 2015
Output to stderr or stdout is not always completly written if
you exit the process. Issue happens only on Windows using pipes.

Issue nodejs/node-v0.x-archive#3584 will be fixed in
node.js 0.12.
pmeijer pushed a commit to webgme/webgme that referenced this issue Apr 6, 2015
@pgilad
Copy link

pgilad commented 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
Copy link
Contributor

Yes, it is resolved. It was fixed with 20176a9.
You shouldn't need the workaround anymore.

@pgilad
Copy link

pgilad commented May 26, 2015

Great, thanks!

@gigapromoters
Copy link

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
Copy link

I wrapped php process in another child script, now it works fine.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.