Skip to content

Commit

Permalink
resolve in-process race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
David Mark Clements committed Nov 24, 2019
1 parent bb034b7 commit 629710a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 3 deletions.
19 changes: 17 additions & 2 deletions index.js
@@ -1,6 +1,10 @@
'use strict';
const net = require('net');

const used = {
old: new Set(),
young: new Set()
};
const getAvailablePort = options => new Promise((resolve, reject) => {
const server = net.createServer();
server.unref();
Expand All @@ -23,14 +27,25 @@ const portCheckSequence = function * (ports) {

module.exports = async options => {
let ports = null;

const sweep = 1000 * 15;
if (options) {
ports = typeof options.port === 'number' ? [options.port] : options.port;
}

const interval = setInterval(() => {
used.old = used.young;
used.young = new Set();
}, sweep);
interval.unref();
for (const port of portCheckSequence(ports)) {
try {
return await getAvailablePort({...options, port}); // eslint-disable-line no-await-in-loop
let p = await getAvailablePort({...options, port}); // eslint-disable-line no-await-in-loop
while (used.old.has(p) || used.young.has(p)) {
p = await getAvailablePort({...options, port}); // eslint-disable-line no-await-in-loop
}

used.young.add(p);
return p;
} catch (error) {
if (error.code !== 'EADDRINUSE') {
throw error;
Expand Down
2 changes: 1 addition & 1 deletion test.js
Expand Up @@ -44,7 +44,7 @@ test('port can be bound to IPv4 host when promise resolves', async t => {
});

test('preferred port given IPv4 host', async t => {
const desiredPort = 8080;
const desiredPort = 8081;
const port = await getPort({
port: desiredPort,
host: '0.0.0.0'
Expand Down

0 comments on commit 629710a

Please sign in to comment.