Skip to content

Commit

Permalink
dgram: remove listeners on bind error
Browse files Browse the repository at this point in the history
This avoids piling up `'listening'` event listeners if
`.bind()` fails repeatedly.

Fixes: #30209

PR-URL: #30210
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
addaleax authored and MylesBorins committed Nov 17, 2019
1 parent 0433d79 commit f8ee70c
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
17 changes: 15 additions & 2 deletions lib/dgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,21 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {

state.bindState = BIND_STATE_BINDING;

if (arguments.length && typeof arguments[arguments.length - 1] === 'function')
this.once('listening', arguments[arguments.length - 1]);
const cb = arguments.length && arguments[arguments.length - 1];
if (typeof cb === 'function') {
function removeListeners() {
this.removeListener('error', removeListeners);
this.removeListener('listening', onListening);
}

function onListening() {
removeListeners.call(this);
cb.call(this);
}

this.on('error', removeListeners);
this.on('listening', onListening);
}

if (port instanceof UDP) {
replaceHandle(this, port);
Expand Down
27 changes: 27 additions & 0 deletions test/parallel/test-dgram-bind-error-repeat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict';
const common = require('../common');
const dgram = require('dgram');

// Regression test for https://github.com/nodejs/node/issues/30209
// No warning should be emitted when re-trying `.bind()` on UDP sockets
// repeatedly.

process.on('warning', common.mustNotCall());

const reservePortSocket = dgram.createSocket('udp4');
reservePortSocket.bind(() => {
const { port } = reservePortSocket.address();

const newSocket = dgram.createSocket('udp4');

let errors = 0;
newSocket.on('error', common.mustCall(() => {
if (++errors < 20) {
newSocket.bind(port, common.mustNotCall());
} else {
newSocket.close();
reservePortSocket.close();
}
}, 20));
newSocket.bind(port, common.mustNotCall());
});

0 comments on commit f8ee70c

Please sign in to comment.