diff --git a/lib/net.js b/lib/net.js index 13b33a45b76..aa6e043ea43 100644 --- a/lib/net.js +++ b/lib/net.js @@ -194,7 +194,9 @@ Object.defineProperty(Socket.prototype, 'bufferSize', { Socket.prototype.pause = function() { - this._handle.readStop(); + if (this._handle) { + this._handle.readStop(); + } }; diff --git a/lib/tty.js b/lib/tty.js index 78971dda315..32ba512d525 100644 --- a/lib/tty.js +++ b/lib/tty.js @@ -83,8 +83,19 @@ function ReadStream(fd) { this.on('newListener', onNewListener); } inherits(ReadStream, net.Socket); + exports.ReadStream = ReadStream; +ReadStream.prototype.pause = function() { + this._handle.unref(); + return net.Socket.prototype.pause.call(this); +}; + +ReadStream.prototype.resume = function() { + this._handle.ref(); + return net.Socket.prototype.resume.call(this); +}; + ReadStream.prototype.isTTY = true; diff --git a/src/handle_wrap.cc b/src/handle_wrap.cc index 6e07643893c..5b6594a3a90 100644 --- a/src/handle_wrap.cc +++ b/src/handle_wrap.cc @@ -64,8 +64,10 @@ Handle HandleWrap::Unref(const Arguments& args) { UNWRAP - // Calling this function twice should never happen. - assert(wrap->unref == false); + // Calling unnecessarily is a no-op + if (wrap->unref) { + return v8::Undefined(); + } wrap->unref = true; uv_unref(uv_default_loop()); @@ -74,6 +76,24 @@ Handle HandleWrap::Unref(const Arguments& args) { } +// Adds a reference to keep uv alive because of this thing. +Handle HandleWrap::Ref(const Arguments& args) { + HandleScope scope; + + UNWRAP + + // Calling multiple times is a no-op + if (!wrap->unref) { + return v8::Undefined(); + } + + wrap->unref = false; + uv_ref(uv_default_loop()); + + return v8::Undefined(); +} + + Handle HandleWrap::Close(const Arguments& args) { HandleScope scope; @@ -82,10 +102,8 @@ Handle HandleWrap::Close(const Arguments& args) { assert(!wrap->object_.IsEmpty()); uv_close(wrap->handle__, OnClose); - if (wrap->unref) { - uv_ref(uv_default_loop()); - wrap->unref = false; - } + + HandleWrap::Ref(args); wrap->StateChange(); diff --git a/src/handle_wrap.h b/src/handle_wrap.h index fc6d623ac65..b9cf31e8eb1 100644 --- a/src/handle_wrap.h +++ b/src/handle_wrap.h @@ -49,6 +49,7 @@ class HandleWrap { static void Initialize(v8::Handle target); static v8::Handle Close(const v8::Arguments& args); static v8::Handle Unref(const v8::Arguments& args); + static v8::Handle Ref(const v8::Arguments& args); protected: HandleWrap(v8::Handle object, uv_handle_t* handle); diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index a2a4203a804..1870837bcae 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -85,6 +85,7 @@ void PipeWrap::Initialize(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close); NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref); + NODE_SET_PROTOTYPE_METHOD(t, "ref", HandleWrap::Ref); NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart); NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop); diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index b46e6c4e1fd..486c2a70b4b 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -69,6 +69,7 @@ class TTYWrap : StreamWrap { NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close); NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref); + NODE_SET_PROTOTYPE_METHOD(t, "ref", HandleWrap::Ref); NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart); NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop); diff --git a/test/simple/test-stdin-pause-resume.js b/test/simple/test-stdin-pause-resume.js new file mode 100644 index 00000000000..cfa44bae2c0 --- /dev/null +++ b/test/simple/test-stdin-pause-resume.js @@ -0,0 +1,37 @@ +// 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. + +console.error("before opening stdin"); +process.stdin.resume(); +console.error("stdin opened"); +setTimeout(function() { + console.error("pausing stdin"); + process.stdin.pause(); + setTimeout(function() { + console.error("opening again"); + process.stdin.resume(); + setTimeout(function() { + console.error("pausing again"); + process.stdin.pause(); + console.error("should exit now"); + }, 1); + }, 1); +}, 1);