Skip to content

Commit a2a711a

Browse files
committed
dgram: generalized send queue to handle close
If the udp socket is not ready and we are accumulating messages to send, it needs to delay closing the socket when all messages are flushed. Fixes: #7061 PR-URL: #7066 Reviewed-By: Anna Henningsen <[email protected]>
1 parent c01d61a commit a2a711a

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

lib/dgram.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -283,20 +283,25 @@ function fixBufferList(list) {
283283
function enqueue(self, toEnqueue) {
284284
// If the send queue hasn't been initialized yet, do it, and install an
285285
// event handler that flushes the send queue after binding is done.
286-
if (!self._sendQueue) {
287-
self._sendQueue = [];
288-
self.once('listening', function() {
289-
// Flush the send queue.
290-
for (var i = 0; i < this._sendQueue.length; i++)
291-
this.send.apply(self, this._sendQueue[i]);
292-
this._sendQueue = undefined;
293-
});
286+
if (!self._queue) {
287+
self._queue = [];
288+
self.once('listening', clearQueue);
294289
}
295-
self._sendQueue.push(toEnqueue);
290+
self._queue.push(toEnqueue);
296291
return;
297292
}
298293

299294

295+
function clearQueue() {
296+
const queue = this._queue;
297+
this._queue = undefined;
298+
299+
// Flush the send queue.
300+
for (var i = 0; i < queue.length; i++)
301+
queue[i]();
302+
}
303+
304+
300305
// valid combinations
301306
// send(buffer, offset, length, port, address, callback)
302307
// send(buffer, offset, length, port, address)
@@ -353,7 +358,7 @@ Socket.prototype.send = function(buffer,
353358
// If the socket hasn't been bound yet, push the outbound packet onto the
354359
// send queue and send after binding is complete.
355360
if (self._bindState != BIND_STATE_BOUND) {
356-
enqueue(self, [list, port, address, callback]);
361+
enqueue(self, self.send.bind(self, list, port, address, callback));
357362
return;
358363
}
359364

@@ -407,10 +412,15 @@ function afterSend(err, sent) {
407412
this.callback(err, sent);
408413
}
409414

410-
411415
Socket.prototype.close = function(callback) {
412416
if (typeof callback === 'function')
413417
this.on('close', callback);
418+
419+
if (this._queue) {
420+
this._queue.push(this.close.bind(this));
421+
return this;
422+
}
423+
414424
this._healthCheck();
415425
this._stopReceiving();
416426
this._handle.close();
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
// Ensure that if a dgram socket is closed before the sendQueue is drained
3+
// will not crash
4+
5+
const common = require('../common');
6+
const dgram = require('dgram');
7+
8+
const buf = Buffer.alloc(1024, 42);
9+
10+
const socket = dgram.createSocket('udp4');
11+
12+
socket.on('listening', function() {
13+
socket.close();
14+
});
15+
16+
// adds a listener to 'listening' to send the data when
17+
// the socket is available
18+
socket.send(buf, 0, buf.length, common.PORT, 'localhost');

0 commit comments

Comments
 (0)