diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-07 22:17:27 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-07 22:22:51 +0200 |
| commit | b06338abf7a5be58151828acb801286c05a3d62a (patch) | |
| tree | 32ba77301f9f8f798f6aba953ce02fd9b5a57235 /packages/meshbay-client | |
| parent | e0dde3466fcb06570cc41b1c379707b2807040ad (diff) | |
| download | meshbay-b06338abf7a5be58151828acb801286c05a3d62a.tar.gz | |
fix(client): stop the node at Quit in "only while open", whoever started it
Switching from "at sign-in" to "only while MeshBay is open" left the node the
sign-in launcher had started running after Quit: only a node this process had
started was stopped. In that mode the app owns the node, so Quit stops the
one that is there.
The start with the app and the sign-in's own start (ensureNode) also both ran
`autostart start` at launch -- three meshbay-node.exe were seen racing for the
port. The sign-in's start and node:start now wait for the launch's.
The end-to-end test covers the mode: Quit leaves no node, opening the app
starts one. It launches the app with the environment it was imported with:
the suite's conftest points HOME, USERPROFILE, LOCALAPPDATA and APPDATA at a
throwaway directory per test, and the app started under that crashed at once
(0x80000003), which first looked like a crash of the app itself.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-client')
| -rw-r--r-- | packages/meshbay-client/src/main.js | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js index 8e987d3..f01b8f2 100644 --- a/packages/meshbay-client/src/main.js +++ b/packages/meshbay-client/src/main.js @@ -558,9 +558,9 @@ let trayTimer = null; // there already do what hiding to an indicator does elsewhere. const trayOS = () => process.platform === 'linux' || process.platform === 'win32'; let nodeService = null; // assigned by registerBridge() -// Whether this app started the node that runs now, outside service mode: in -// the installer's "only while MeshBay is open" mode that is the node it stops -// when it quits. +// Whether this app started the node that runs now, outside service mode. In +// "only while MeshBay is open" the node is stopped at Quit whoever started it; +// this only saves asking whether one is there. let nodeStartedByApp = false; let nodeWithApp = null; // assigned by registerBridge() @@ -1537,6 +1537,11 @@ function registerBridge() { // each mode of a real install. A node not yet set up (no account in // node.toml) is left alone -- node:start provisions and starts it. async function winStartNodeWithApp() { + if (!nodeWithAppStart) nodeWithAppStart = winStartNodeWithAppOnce(); + return nodeWithAppStart; + } + + async function winStartNodeWithAppOnce() { if (process.platform !== 'win32' || !hasBundledNode() || !nodeProvisioned()) return; if ((await winStartupMode()) !== 'open' || await probeNode()) return; try { @@ -1546,15 +1551,27 @@ function registerBridge() { console.error('[node] start with the app:', err.message); } } + // The start at launch, while it runs: the sign-in's own start (ensureNode) + // and node:start wait for it. Both used to run `autostart start` at once, + // and three meshbay-node.exe were seen racing for the port. + let nodeWithAppStart = null; nodeWithApp = { start: winStartNodeWithApp }; + // In "only while MeshBay is open" the app owns the node, whoever started it: + // one left by the sign-in launcher before the mode was switched, or started + // from a terminal, ran on after Quit because only a node this process had + // started was stopped (found switching modes on a real install). let nodeStopAtQuitDone = false; app.on('before-quit', (event) => { - if (process.platform !== 'win32' || nodeStopAtQuitDone || !nodeStartedByApp) return; + if (process.platform !== 'win32' || nodeStopAtQuitDone || !hasBundledNode()) return; event.preventDefault(); // before-quit waits for no promise nodeStopAtQuitDone = true; - winStartupMode() - .then((mode) => (mode === 'open' ? killNodeProcesses() : null)) + (async () => { + if ((await winStartupMode()) !== 'open') return; + if (nodeStartedByApp || await probeNode() || (await winNodePids()).length) { + await killNodeProcesses(); + } + })() .catch((err) => console.error('[node] stop at quit:', err.message)) .finally(() => app.quit()); }); @@ -2033,6 +2050,7 @@ Its log: ${nodeLogHint()}`); async function ensureNode(opts) { if (process.platform !== 'win32' || !hasBundledNode()) return { state: 'unsupported' }; + if (nodeWithAppStart) await nodeWithAppStart.catch(() => {}); const hubUrl = String(config.hubBase || '').replace(/\/+$/, ''); const username = String((opts && opts.username) || ''); const token = opts && opts.token; @@ -2083,6 +2101,7 @@ Its log: ${nodeLogHint()}`); handle('node:start', async (_e, opts) => { // One at a time: a start racing the sign-in's own would stop the node the // other had just started. + if (nodeWithAppStart) await nodeWithAppStart.catch(() => {}); if (nodeEnsuring) await nodeEnsuring.catch(() => {}); const already = await probeNode(); if (already && already.status === 'running') { |