diff --git a/lib/net.js b/lib/net.js index 981ee876ba0dbb..27eac453e9f95e 100644 --- a/lib/net.js +++ b/lib/net.js @@ -80,6 +80,7 @@ const { } = errors.codes; const { validateInt32, validateString } = require('internal/validators'); const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); +const kShouldShutdown = Symbol('shouldShutdown'); // Lazy loaded to improve startup performance. let cluster; @@ -245,6 +246,10 @@ function Socket(options) { options.writable = options.writable || false; const { allowHalfOpen } = options; + // Needed to avoid to call uv_shutdown during _final + // as otherwise it would error with an ENOTCONN. + this[kShouldShutdown] = options.writable; + // Prevent the "no-half-open enforcer" from being inherited from `Duplex`. options.allowHalfOpen = true; // For backwards compat do not emit close on destroy. @@ -359,7 +364,7 @@ Socket.prototype._final = function(cb) { debug('_final: not ended, call shutdown()'); // otherwise, just shutdown, or destroy() if not possible - if (!this._handle || !this._handle.shutdown) { + if (!this[kShouldShutdown] || !this._handle || !this._handle.shutdown) { cb(); return this.destroy(); } diff --git a/lib/tty.js b/lib/tty.js index 62eb8719b114b9..9f6cbd604e22e6 100644 --- a/lib/tty.js +++ b/lib/tty.js @@ -66,6 +66,7 @@ function ReadStream(fd, options) { } inherits(ReadStream, net.Socket); + ReadStream.prototype.setRawMode = function(flag) { flag = !!flag; this._handle.setRawMode(flag); diff --git a/test/pseudo-tty/test-tty-stdin-call-end.js b/test/pseudo-tty/test-tty-stdin-call-end.js new file mode 100644 index 00000000000000..e3c3fd9af469ba --- /dev/null +++ b/test/pseudo-tty/test-tty-stdin-call-end.js @@ -0,0 +1,8 @@ +'use strict'; + +require('../common'); + +// This tests verifies that process.stdin.end() does not +// crash the process with ENOTCONN + +process.stdin.end(); diff --git a/test/pseudo-tty/test-tty-stdin-call-end.out b/test/pseudo-tty/test-tty-stdin-call-end.out new file mode 100644 index 00000000000000..e69de29bb2d1d6