Skip to content

Commit 5094658

Browse files
committed
fix(daemon): throw instead of silent return when RPC port races
createOrConnectRpc had an early `if (isRpcPortTaken) return` meant to be defensive. But startedOwnRpc already short-circuits every tick call once our server is up, so that branch is only reachable during initial startup in a TOCTOU race where the port becomes occupied between the pre-flight fail-fast check and the actual bind. Today the daemon silently continues with kubo running but no RPC server and no web UI; throw instead so startup fails fast with the port in the message.
1 parent 06693ba commit 5094658

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

src/cli/commands/daemon.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,15 @@ export default class Daemon extends Command {
432432
const createOrConnectRpc = async () => {
433433
if (mainProcessExited) return;
434434
if (startedOwnRpc) return;
435-
// Tick may call this after our own server is up — port being taken means our server is still healthy.
435+
// Re-check the port: the early fail-fast at startup is a few ms before this runs,
436+
// so a TOCTOU race could let another process grab the port in between. If that
437+
// happens we must fail rather than silently leaving the daemon without an RPC.
436438
const isRpcPortTaken = await tcpPortUsed.check(Number(pkcRpcUrl.port), rpcConnectHostname);
437-
if (isRpcPortTaken) return;
439+
if (isRpcPortTaken) {
440+
throw new Error(
441+
`PKC RPC port ${pkcRpcUrl.hostname}:${pkcRpcUrl.port} (${pkcRpcUrl}) became occupied before the daemon could bind it.`
442+
);
443+
}
438444

439445
// Load installed challenge packages before starting the RPC server
440446
const loadedChallenges = await loadChallengesIntoPKC(mergedPkcOptions.dataPath);

0 commit comments

Comments
 (0)