From 0b3021ed3389436fe399fdbb02b0d65c23150592 Mon Sep 17 00:00:00 2001 From: Henry Rawas Date: Wed, 12 Jun 2013 17:15:32 -0700 Subject: [PATCH] stdio: Fix issue #3584. Use synch write in pipe When pipe used for stdout or stderr on Windows, pipe does not allow IOCP. In this case do write on calling thread. Added test test-child-process-stdout-flush-exit --- lib/net.js | 7 +- src/node.js | 3 +- src/pipe_wrap.cc | 4 ++ .../test-child-process-stdout-flush-exit.js | 69 +++++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 test/simple/test-child-process-stdout-flush-exit.js diff --git a/lib/net.js b/lib/net.js index 7f6f306b8465..ff9398feacb7 100644 --- a/lib/net.js +++ b/lib/net.js @@ -154,7 +154,12 @@ function Socket(options) { this._handle = options.handle; // private } else if (typeof options.fd !== 'undefined') { this._handle = createHandle(options.fd); - this._handle.open(options.fd); + if (typeof options.blocking !== 'undefined') { + // blocking flag used for stdout over pipe + this._handle.open(options.fd, options.blocking); + } else { + this._handle.open(options.fd); + } this.readable = options.readable !== false; this.writable = options.writable !== false; } else { diff --git a/src/node.js b/src/node.js index e5833cb5cc8e..235432845ca6 100644 --- a/src/node.js +++ b/src/node.js @@ -574,7 +574,8 @@ stream = new net.Socket({ fd: fd, readable: false, - writable: true + writable: true, + blocking: true }); // FIXME Should probably have an option in net.Socket to create a diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 3952a0799c4d..7be5a8c3075e 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -273,6 +273,10 @@ Handle PipeWrap::Open(const Arguments& args) { uv_pipe_open(&wrap->handle_, fd); + if (args.Length() > 1 && args[1]->IsTrue()) { + uv_stream_set_blocking((uv_stream_t*)&wrap->handle_, 1); + } + return scope.Close(v8::Null()); } diff --git a/test/simple/test-child-process-stdout-flush-exit.js b/test/simple/test-child-process-stdout-flush-exit.js new file mode 100644 index 000000000000..49a0ec0e5f71 --- /dev/null +++ b/test/simple/test-child-process-stdout-flush-exit.js @@ -0,0 +1,69 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + +var common = require('../common'); +var assert = require('assert'); +var path = require('path'); + +// if child process output to console and exit +if (process.argv[2] === 'child') { + console.log('hello'); + for (var i = 0; i < 200; i++) { + console.log('filler'); + } + console.log('goodbye'); + process.exit(0); +} else { + // parent process + var spawn = require('child_process').spawn; + + // spawn self as child + var child = spawn(process.argv[0], [process.argv[1], 'child']); + + var gotHello = false; + var gotBye = false; + + child.stderr.setEncoding('utf8'); + child.stderr.on('data', function (data) { + console.log('parent stderr: ' + data); + assert.ok(false); + }); + + // check if we receive both 'hello' at start and 'goodbye' at end + child.stdout.setEncoding('utf8'); + child.stdout.on('data', function (data) { + if (data.slice(0, 6) == 'hello\n') { + gotHello = true; + } else if (data.slice(data.length - 8) == 'goodbye\n') { + gotBye = true; + } else { + gotBye = false; + } + }); + + child.on('close', function (data) { + assert(gotHello); + assert(gotBye); + }); +}