From 464bfdec13908d7508547063af3c39ee3522b3b6 Mon Sep 17 00:00:00 2001 From: Ryan Block Date: Mon, 23 Oct 2023 18:30:51 -0700 Subject: [PATCH] Work around qemu/emulator port conflicts by using `net.createConnection` instead of `net.createServer` --- changelog.md | 7 ++++++- src/sandbox/ports.js | 44 +++++++++++++++++++++++--------------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/changelog.md b/changelog.md index 87ef5a6e..6dc47e52 100644 --- a/changelog.md +++ b/changelog.md @@ -2,12 +2,17 @@ --- -## [5.8.4] 2023-10-23 +## [5.8.4 - 5.8.5] 2023-10-23 ### Added - Added support for hydration of platform-specific binary deps (namely: Python); fixes #1457 + +### Fixed + +- Fixed issue where qemu/emulator port conflicts were not detected with our open port tester; fixes 1441 + --- ## [5.8.3] 2023-10-17 diff --git a/src/sandbox/ports.js b/src/sandbox/ports.js index 756cc21e..eadbb961 100644 --- a/src/sandbox/ports.js +++ b/src/sandbox/ports.js @@ -71,36 +71,38 @@ module.exports = function getPorts (params, callback) { */ function checkPort (checking, ports, name, single, callback) { let tries = 0 - let tester = net.createServer() let done = false function check () { if (tries === 50) { let msg = `Could not find open port after 50 tries, please close some applications and try again` return callback(Error(msg)) } - tester.listen(checking) - tester.once('error', err => { - if (err.message.includes('EADDRINUSE')) { - if (single) { - return callback(Error(`Port ${checking} (${name}) is already in use, please select another with prefs.arc\nSee https://arc.codes/docs/en/reference/configuration/local-preferences#ports---list for config`)) - } - else { - tries++ - checking++ - return check() - } + let client = net.createConnection({ port: checking }, () => { + if (single) { + return callback(Error(`Port ${checking} (${name}) is already in use, please select another with prefs.arc\nSee https://arc.codes/docs/en/reference/configuration/local-preferences#ports---list for config`)) + } + else { + tries++ + checking++ + return client.end(check) } }) - tester.once('listening', () => { - tester.close(() => { - // Tester close emits multiple events, so only call back once - if (!done) { - done = true - if (Object.values(ports).includes(checking)) { - return callback(Error(`Port conflict found on ${checking}, please specify another port`)) + client.once('error', err => { + client.end(() => { + if (err.code === 'ECONNREFUSED') { + // Tester close emits multiple events, so only call back once + if (!done) { + done = true + if (Object.values(ports).includes(checking)) { + return callback(Error(`Port conflict found on ${checking}, please specify another port`)) + } + ports[name] = checking + callback() } - ports[name] = checking - callback() + } + else { + console.error(`Unknown port checking error`) + return callback(err) } }) })