Skip to content

Commit c232d30

Browse files
authored
fix: restart Apple container networking via supported API (#48)
Signed-off-by: Joseph Yaksich <gitcommit90@users.noreply.github.com> Co-authored-by: Joseph Yaksich <gitcommit90@users.noreply.github.com>
1 parent 4610efe commit c232d30

3 files changed

Lines changed: 9 additions & 5 deletions

File tree

src/server/channel-computers.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,12 +592,14 @@ async function repairAppleGuestNetwork(computer: ChannelComputer): Promise<void>
592592
// Avoid repeatedly bouncing shared vmnet while several machines detect
593593
// the same fleet-wide outage during one reconciliation pass.
594594
if (now() - appleNetworkRepairAt > 30_000) {
595-
if (platform() === "darwin") {
596-
const label = `gui/${process.getuid?.() ?? 501}/com.apple.container.network.container-network-vmnet.default`;
597-
const kicked = await spawnCollected("/bin/launchctl", ["kickstart", "-k", label], { timeoutMs: 30_000 });
598-
if (kicked.code !== 0) throw new Error(kicked.stderr.toString("utf8").trim() || "Apple shared VM network service could not restart");
595+
const activeCommands = Number(q1("SELECT COUNT(*) n FROM channel_computer_obligations WHERE kind='command' AND status='active'")?.n || 0);
596+
const activeTurns = Number(q1("SELECT COUNT(*) n FROM agent_turns WHERE state='running'")?.n || 0);
597+
if (terminalSessions.size > 0 || activeCommands > 1 || activeTurns > 1) {
598+
throw new Error("resident computer network is unavailable; automatic repair is waiting for concurrent work to finish");
599599
}
600+
const stopped = await apple(["system", "stop"], { timeoutMs: 90_000 });
600601
const started = await apple(["system", "start"], { timeoutMs: 90_000 });
602+
if (stopped.code !== 0) throw new Error(stopped.stderr.toString("utf8").trim() || "Apple container services could not stop for network recovery");
601603
if (started.code !== 0) throw new Error(started.stderr.toString("utf8").trim() || "Apple container services could not restart");
602604
appleNetworkRepairAt = now();
603605
}

test/channel-computers.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ test("Apple channel-computer contract preserves isolation, files, wakes, archive
154154
assert.ok(calls.some((call) => call.includes("-w") && call.includes("/workspace") && call.some((word) => word.includes("/bin/bash")) && call.some((word) => word.includes("-lc"))), "resident commands execute in the correct VM workspace");
155155
assert.equal(db.q1("SELECT disk_bytes FROM channel_computers WHERE channel_id=?", beta.channelId).disk_bytes, computers.MANAGED_CHANNEL_DISK_BYTES, "reported storage is the managed writable allocation, not Apple's host-backed virtual capacity");
156156
const backend = await readFile(join(root, "src", "server", "channel-computers.ts"), "utf8");
157-
assert.match(backend, /com\.apple\.container\.network\.container-network-vmnet\.default/, "network recovery restarts Apple's installed vmnet launch service");
157+
assert.match(backend, /apple\(\["system", "stop"\]/, "network recovery uses Apple's supported service stop operation");
158+
assert.match(backend, /apple\(\["system", "start"\]/, "network recovery uses Apple's supported service start operation");
158159
assert.match(backend, /terminal \? \["-it"\] : pipeInput \? \["-i"\]/, "Apple terminal and streamed-stdin invocations request the exact interactive mode they need");
159160
assert.match(backend, /isolatedInvocation\(\["\/bin\/bash", "-l"\][\s\S]*true\)/, "interactive isolated terminals request an explicit guest login shell");
160161
assert.match(backend, /args: \[\.\.\.words, \.\.\.guestWords\(\.\.\.args\)\]/, "Apple guest argv remains quoted for the runtime's documented second shell parse");

test/fake-container.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ if (args[0] === "system" && args[1] === "status") {
3131
process.stdout.write(JSON.stringify({ status: "running" }));
3232
process.exit(0);
3333
}
34+
if (args[0] === "system" && args[1] === "stop") process.exit(0);
3435
if (args[0] === "system" && args[1] === "start") {
3536
for (const entry of readdirSync(join(stateRoot, "machines"))) rmSync(join(stateRoot, "machines", entry, ".network-down"), { force: true });
3637
process.exit(0);

0 commit comments

Comments
 (0)