diff --git a/lib/dgram.js b/lib/dgram.js index a2827df0262800..484689380e26eb 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -243,6 +243,32 @@ Socket.prototype.sendto = function(buffer, }; +function enqueue(self, toEnqueue) { + // If the send queue hasn't been initialized yet, do it, and install an + // event handler that flushes the send queue after binding is done. + if (!self._queue) { + self._queue = []; + self.once('listening', clearQueue); + } + self._queue.push(toEnqueue); + return; +} + + +function clearQueue() { + const queue = this._queue; + this._queue = undefined; + + // Flush the send queue. + for (var i = 0; i < queue.length; i++) + queue[i](); +} + + +// valid combinations +// send(buffer, offset, length, port, address, callback) +// send(buffer, offset, length, port, address) +// send(buffer, offset, length, port) Socket.prototype.send = function(buffer, offset, length, @@ -290,18 +316,13 @@ Socket.prototype.send = function(buffer, // If the socket hasn't been bound yet, push the outbound packet onto the // send queue and send after binding is complete. if (self._bindState != BIND_STATE_BOUND) { - // If the send queue hasn't been initialized yet, do it, and install an - // event handler that flushes the send queue after binding is done. - if (!self._sendQueue) { - self._sendQueue = []; - self.once('listening', function() { - // Flush the send queue. - for (var i = 0; i < self._sendQueue.length; i++) - self.send.apply(self, self._sendQueue[i]); - self._sendQueue = undefined; - }); - } - self._sendQueue.push([buffer, offset, length, port, address, callback]); + enqueue(self, self.send.bind(self, + buffer, + offset, + length, + port, + address, + callback)); return; } @@ -347,10 +368,15 @@ function afterSend(err) { this.callback(err, this.length); } - Socket.prototype.close = function(callback) { if (typeof callback === 'function') this.on('close', callback); + + if (this._queue) { + this._queue.push(this.close.bind(this)); + return this; + } + this._healthCheck(); this._stopReceiving(); this._handle.close(); diff --git a/test/parallel/test-dgram-close-in-listening.js b/test/parallel/test-dgram-close-in-listening.js new file mode 100644 index 00000000000000..e181f40de67dcf --- /dev/null +++ b/test/parallel/test-dgram-close-in-listening.js @@ -0,0 +1,18 @@ +'use strict'; +// Ensure that if a dgram socket is closed before the sendQueue is drained +// will not crash + +const common = require('../common'); +const dgram = require('dgram'); + +const buf = Buffer.alloc(1024, 42); + +const socket = dgram.createSocket('udp4'); + +socket.on('listening', function() { + socket.close(); +}); + +// adds a listener to 'listening' to send the data when +// the socket is available +socket.send(buf, 0, buf.length, common.PORT, 'localhost');