net: use _final
instead of on('finish')
Shutting down the connection is what `_final` is there for. PR-URL: https://github.com/nodejs/node/pull/18608 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
parent
6bdc18c592
commit
03ddd13d8a
@ -55,6 +55,8 @@ function undestroy() {
|
|||||||
this._writableState.destroyed = false;
|
this._writableState.destroyed = false;
|
||||||
this._writableState.ended = false;
|
this._writableState.ended = false;
|
||||||
this._writableState.ending = false;
|
this._writableState.ending = false;
|
||||||
|
this._writableState.finalCalled = false;
|
||||||
|
this._writableState.prefinished = false;
|
||||||
this._writableState.finished = false;
|
this._writableState.finished = false;
|
||||||
this._writableState.errorEmitted = false;
|
this._writableState.errorEmitted = false;
|
||||||
}
|
}
|
||||||
|
28
lib/net.js
28
lib/net.js
@ -256,7 +256,6 @@ function Socket(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shut down the socket when we're finished with it.
|
// shut down the socket when we're finished with it.
|
||||||
this.on('finish', onSocketFinish);
|
|
||||||
this.on('_socketEnd', onSocketEnd);
|
this.on('_socketEnd', onSocketEnd);
|
||||||
|
|
||||||
initSocketHandle(this);
|
initSocketHandle(this);
|
||||||
@ -303,39 +302,42 @@ Socket.prototype._unrefTimer = function _unrefTimer() {
|
|||||||
|
|
||||||
function shutdownSocket(self, callback) {
|
function shutdownSocket(self, callback) {
|
||||||
var req = new ShutdownWrap();
|
var req = new ShutdownWrap();
|
||||||
req.oncomplete = callback;
|
req.oncomplete = afterShutdown;
|
||||||
req.handle = self._handle;
|
req.handle = self._handle;
|
||||||
|
req.callback = callback;
|
||||||
return self._handle.shutdown(req);
|
return self._handle.shutdown(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the user has called .end(), and all the bytes have been
|
// the user has called .end(), and all the bytes have been
|
||||||
// sent out to the other side.
|
// sent out to the other side.
|
||||||
function onSocketFinish() {
|
Socket.prototype._final = function(cb) {
|
||||||
// If still connecting - defer handling 'finish' until 'connect' will happen
|
// If still connecting - defer handling `_final` until 'connect' will happen
|
||||||
if (this.connecting) {
|
if (this.connecting) {
|
||||||
debug('osF: not yet connected');
|
debug('_final: not yet connected');
|
||||||
return this.once('connect', onSocketFinish);
|
return this.once('connect', () => this._final(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
debug('onSocketFinish');
|
|
||||||
if (!this.readable || this._readableState.ended) {
|
if (!this.readable || this._readableState.ended) {
|
||||||
debug('oSF: ended, destroy', this._readableState);
|
debug('_final: ended, destroy', this._readableState);
|
||||||
|
cb();
|
||||||
return this.destroy();
|
return this.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
debug('oSF: not ended, call shutdown()');
|
debug('_final: not ended, call shutdown()');
|
||||||
|
|
||||||
// otherwise, just shutdown, or destroy() if not possible
|
// otherwise, just shutdown, or destroy() if not possible
|
||||||
if (!this._handle || !this._handle.shutdown)
|
if (!this._handle || !this._handle.shutdown) {
|
||||||
|
cb();
|
||||||
return this.destroy();
|
return this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
var err = defaultTriggerAsyncIdScope(
|
var err = defaultTriggerAsyncIdScope(
|
||||||
this[async_id_symbol], shutdownSocket, this, afterShutdown
|
this[async_id_symbol], shutdownSocket, this, cb
|
||||||
);
|
);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return this.destroy(errnoException(err, 'shutdown'));
|
return this.destroy(errnoException(err, 'shutdown'));
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function afterShutdown(status, handle) {
|
function afterShutdown(status, handle) {
|
||||||
@ -344,6 +346,8 @@ function afterShutdown(status, handle) {
|
|||||||
debug('afterShutdown destroyed=%j', self.destroyed,
|
debug('afterShutdown destroyed=%j', self.destroyed,
|
||||||
self._readableState);
|
self._readableState);
|
||||||
|
|
||||||
|
this.callback();
|
||||||
|
|
||||||
// callback may come after call to destroy.
|
// callback may come after call to destroy.
|
||||||
if (self.destroyed)
|
if (self.destroyed)
|
||||||
return;
|
return;
|
||||||
|
@ -24,11 +24,13 @@ let endedConnection = false;
|
|||||||
function onconnection(c) {
|
function onconnection(c) {
|
||||||
assert.strictEqual(hooks.activitiesOfTypes('SHUTDOWNWRAP').length, 0);
|
assert.strictEqual(hooks.activitiesOfTypes('SHUTDOWNWRAP').length, 0);
|
||||||
c.end();
|
c.end();
|
||||||
endedConnection = true;
|
process.nextTick(() => {
|
||||||
const as = hooks.activitiesOfTypes('SHUTDOWNWRAP');
|
endedConnection = true;
|
||||||
assert.strictEqual(as.length, 1);
|
const as = hooks.activitiesOfTypes('SHUTDOWNWRAP');
|
||||||
checkInvocations(as[0], { init: 1 }, 'after ending client connection');
|
assert.strictEqual(as.length, 1);
|
||||||
this.close(onserverClosed);
|
checkInvocations(as[0], { init: 1 }, 'after ending client connection');
|
||||||
|
this.close(onserverClosed);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onconnected() {
|
function onconnected() {
|
||||||
|
@ -185,3 +185,17 @@ const { inherits } = require('util');
|
|||||||
assert.strictEqual(expected, err);
|
assert.strictEqual(expected, err);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Checks that `._undestroy()` restores the state so that `final` will be
|
||||||
|
// called again.
|
||||||
|
const write = new Writable({
|
||||||
|
write: common.mustNotCall(),
|
||||||
|
final: common.mustCall((cb) => cb(), 2)
|
||||||
|
});
|
||||||
|
|
||||||
|
write.end();
|
||||||
|
write.destroy();
|
||||||
|
write._undestroy();
|
||||||
|
write.end();
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user