diff options
author | Trevor Norris <trev.norris@gmail.com> | 2013-12-31 03:08:54 -0800 |
---|---|---|
committer | Trevor Norris <trev.norris@gmail.com> | 2014-01-04 03:04:13 -0800 |
commit | 9ff83c32e64a021421a96772ae96057b81a5f084 (patch) | |
tree | a8c4422a3854d8c56c177a72454f14bcc9d8f601 | |
parent | a40b46367406deb0e3c67dff8c5d609d1334519b (diff) | |
download | node-9ff83c32e64a021421a96772ae96057b81a5f084.tar.gz |
net: run close callbacks in correct eloop phase
Instead of running the close callbacks seemingly synchronously instead
of when the handle has actually been closed by libuv, instead run the
callbacks in the uv__run_closing_handles() phase of the eloop.
-rw-r--r-- | lib/net.js | 85 |
1 files changed, 42 insertions, 43 deletions
diff --git a/lib/net.js b/lib/net.js index afb2d0dec..b49cd8c19 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1078,11 +1078,10 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) { if (err) { var ex = errnoException(err, 'listen'); - self._handle.close(); - self._handle = null; - process.nextTick(function() { + self._handle.close(function() { self.emit('error', ex); }); + self._handle = null; return; } @@ -1276,58 +1275,58 @@ Server.prototype.getConnections = function(cb) { }; -Server.prototype.close = function(cb) { - function onSlaveClose() { - if (--left !== 0) return; +function emitWhenClosed(self) { + debug('SERVER: emitWhenClosed'); - self._connections = 0; - self._emitCloseIfDrained(); + if (self._handle || self._connections) { + debug('SERVER handle? %j connections? %d', + !!self._handle, self._connections); + return; } - if (!this._handle) { - // Throw error. Follows net_legacy behaviour. - throw new Error('Not running'); - } + debug('SERVER: emit close'); + self.emit('close'); +} - if (cb) { - this.once('close', cb); - } - this._handle.close(); - this._handle = null; - if (this._usingSlaves) { - var self = this, - left = this._slaves.length; +function closeWhenDrained() { + var self = this.owner; - // Increment connections to be sure that, even if all sockets will be closed - // during polling of slaves, `close` event will be emitted only once. - this._connections++; + // If no slaves then not much more to do. + if (!self._usingSlaves) + return emitWhenClosed(self); - // Poll slaves - this._slaves.forEach(function(slave) { - slave.close(onSlaveClose); + var left = self._slaves.length; + + // Increment connections to be sure that, even if all sockets will be closed + // during polling of slaves, `close` event will be emitted only once. + self.connections++; + + // Poll slaves + self._slaves.forEach(function(slave) { + slave.close(function callOnSlaveClose() { + if (--left > 0) + return; + + self._connections = 0; + emitWhenClosed(self); }); - } else { - this._emitCloseIfDrained(); - } + }); +} - return this; -}; -Server.prototype._emitCloseIfDrained = function() { - debug('SERVER _emitCloseIfDrained'); - var self = this; +Server.prototype.close = function(cb) { + // Throw error. Follows net_legacy behaviour. + if (!this._handle) + throw new Error('Not running'); - if (self._handle || self._connections) { - debug('SERVER handle? %j connections? %d', - !!self._handle, self._connections); - return; - } + if (cb) + this.once('close', cb); - process.nextTick(function() { - debug('SERVER: emit close'); - self.emit('close'); - }); + this._handle.close(closeWhenDrained); + this._handle = null; + + return this; }; |