diff --git a/lib/dgram.js b/lib/dgram.js index e6cc169dc644fe..c088bffa7ff477 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -283,20 +283,25 @@ function fixBufferList(list) { 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._sendQueue) { - self._sendQueue = []; - self.once('listening', function() { - // Flush the send queue. - for (var i = 0; i < this._sendQueue.length; i++) - this.send.apply(self, this._sendQueue[i]); - this._sendQueue = undefined; - }); + if (!self._queue) { + self._queue = []; + self.once('listening', clearQueue); } - self._sendQueue.push(toEnqueue); + 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) @@ -353,7 +358,7 @@ 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) { - enqueue(self, [list, port, address, callback]); + enqueue(self, self.send.bind(self, list, port, address, callback)); return; } @@ -407,10 +412,15 @@ function afterSend(err, sent) { this.callback(err, sent); } - 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..f67d49b36e8a20 --- /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 +// wil 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');