Skip to content

Commit b699090

Browse files
committed
WIP net: enable emitclose in socket
1 parent 6385340 commit b699090

File tree

6 files changed

+34
-23
lines changed

6 files changed

+34
-23
lines changed

lib/internal/streams/destroy.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ const {
66
const {
77
FunctionPrototypeCall,
88
Symbol,
9+
Boolean
910
} = primordials;
10-
1111
const kDestroy = Symbol('kDestroy');
1212
const kConstruct = Symbol('kConstruct');
1313

@@ -155,12 +155,15 @@ function _destroy(self, err, cb) {
155155

156156
function emitErrorCloseNT(self, err) {
157157
emitErrorNT(self, err);
158-
emitCloseNT(self);
158+
emitCloseNT(self, err);
159159
}
160160

161-
function emitCloseNT(self) {
161+
function emitCloseNT(self, err) {
162162
const r = self._readableState;
163163
const w = self._writableState;
164+
const emitClose = (w && w.emitClose) || (r && r.emitClose);
165+
const shouldPassErrorFlag = (w && w.errorFlagOnClose) ||
166+
(r && r.errorFlagOnClose);
164167

165168
if (w) {
166169
w.closeEmitted = true;
@@ -169,8 +172,12 @@ function emitCloseNT(self) {
169172
r.closeEmitted = true;
170173
}
171174

172-
if ((w && w.emitClose) || (r && r.emitClose)) {
173-
self.emit('close');
175+
if (emitClose) {
176+
if (shouldPassErrorFlag) {
177+
self.emit('close', Boolean(err));
178+
} else {
179+
self.emit('close');
180+
}
174181
}
175182
}
176183

lib/internal/streams/readable.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ function ReadableState(options, stream, isDuplex) {
142142
// Should close be emitted on destroy. Defaults to true.
143143
this.emitClose = !options || options.emitClose !== false;
144144

145+
// Should a boolean flag be passed as argument when emitting close if an error
146+
// occurred
147+
this.errorFlagOnClose = options && options.errorFlagOnClose === true;
148+
145149
// Should .destroy() be called after 'end' (and potentially 'finish').
146150
this.autoDestroy = !options || options.autoDestroy !== false;
147151

lib/internal/streams/writable.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ function WritableState(options, stream, isDuplex) {
186186
// Should close be emitted on destroy. Defaults to true.
187187
this.emitClose = !options || options.emitClose !== false;
188188

189+
// Should a boolean flag be passed as argument when emitting close if an error
190+
// occurred
191+
this.errorFlagOnClose = options && options.errorFlagOnClose === true;
192+
189193
// Should .destroy() be called after 'finish' (and potentially 'end').
190194
this.autoDestroy = !options || options.autoDestroy !== false;
191195

lib/net.js

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,9 @@ function Socket(options) {
299299

300300
// Default to *not* allowing half open sockets.
301301
options.allowHalfOpen = Boolean(options.allowHalfOpen);
302-
// For backwards compat do not emit close on destroy.
303-
options.emitClose = false;
302+
// For backward compatibility, pass a flag when emitting close for
303+
// comunicating that an error occurred.
304+
options.errorFlagOnClose = true;
304305
options.autoDestroy = true;
305306
// Handle strings directly.
306307
options.decodeStrings = false;
@@ -655,28 +656,20 @@ Socket.prototype._destroy = function(exception, cb) {
655656
if (this._handle) {
656657
if (this !== process.stderr)
657658
debug('close handle');
658-
const isException = exception ? true : false;
659+
659660
// `bytesRead` and `kBytesWritten` should be accessible after `.destroy()`
660661
this[kBytesRead] = this._handle.bytesRead;
661662
this[kBytesWritten] = this._handle.bytesWritten;
662663

663664
this._handle.close(() => {
664665
debug('emit close');
665-
if (this._writableState) {
666-
this._writableState.closed = true;
667-
}
668-
if (this._readableState) {
669-
this._readableState.closed = true;
670-
}
671-
this.emit('close', isException);
666+
cb(exception);
672667
});
673668
this._handle.onread = noop;
674669
this._handle = null;
675670
this._sockname = null;
676-
cb(exception);
677671
} else {
678672
cb(exception);
679-
process.nextTick(emitCloseNT, this);
680673
}
681674

682675
if (this._server) {
@@ -1655,12 +1648,6 @@ Server.prototype._emitCloseIfDrained = function() {
16551648

16561649
function emitCloseNT(self) {
16571650
debug('SERVER: emit close');
1658-
if (self._writableState) {
1659-
self._writableState.closed = true;
1660-
}
1661-
if (self._readableState) {
1662-
self._readableState.closed = true;
1663-
}
16641651
self.emit('close');
16651652
}
16661653

test/parallel/test-http2-respond-with-file-connection-abort.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ server.listen(0, common.mustCall(() => {
2525

2626
req.on('response', common.mustCall(() => {}));
2727
req.once('data', common.mustCall(() => {
28+
// TODO: is this test needed?
29+
// It errors with ERR_HTTP2_NO_SOCKET_MANIPULATION because we are
30+
// calling destroy on the Proxy(ed) socket of the Http2ClientSession
31+
// which causes `emit` to becalled and the error to be thrown.
2832
net.Socket.prototype.destroy.call(client.socket);
2933
server.close();
3034
}));

test/parallel/test-tls-socket-close.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use strict';
2+
23
const common = require('../common');
34
if (!common.hasCrypto)
45
common.skip('missing crypto');
@@ -8,6 +9,10 @@ const tls = require('tls');
89
const net = require('net');
910
const fixtures = require('../common/fixtures');
1011

12+
// TODO: is this test needed?
13+
// It fails with a timeout error because the `error` event is never emitted.
14+
// `write` doesn't error, is that a good thing?
15+
1116
// Regression test for https://github.com/nodejs/node/issues/8074
1217
//
1318
// This test has a dependency on the order in which the TCP connection is made,

0 commit comments

Comments
 (0)