seat, cli, harness: git kill reach, close bound and host.lock (#1597)
Row 103, the row 100 follow-up. Built by Darkwing, packet
agents/darkwing/work/queue-103/r1/, candidate manifest
6e5ac8c0782bc595d7c0d711d457738ffb42f1ba5f38253912943dd55e55888a.
Sage approved on #1597, comment 28252; Dewey approved, comment 28260.
Host git runs through runGit: a detached group, SIGTERM at the limit,
SIGKILL after the grace, and one more SIGKILL to the group after a
signalled git closes. git-socket close() waits at most 2 s. startHost
claims bus-host/host.lock by hard link before the broker fork.
packages/cli/README.md and tests/host.test.mjs carry row 85's hunks
too; row 85 lands first.
Sage's gate rerun on 3a1e11b83 with rows 85, 102 and 103 applied,
Docker up: node suites bus 128, business 67, cli 165, control-board
124, conversation 182, discord 178, harness 73, ledger 78, mosaic 69,
queue 155, runs 43, seat 113, tasks 92, webui 108; scripts auth 15,
conductor 17, config 24, discord 66, extension-package 18,
foundation 44, queue 28, release 14, task 98. All pass, 0 fail.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
+27
-11
@@ -172,17 +172,31 @@ mosaic bus status [--json] host state file, socket, writer.lock
|
||||
and `readers: [<business>]`. It gets `config.trackers` (below) when a
|
||||
tracker is set.
|
||||
2. It reads the notifier config (below).
|
||||
3. It forks `packages/bus/src/process.mjs` and waits up to 30 s for the boot
|
||||
3. It takes `<dataRoot>/bus-host/host.lock` (0600), which holds the same
|
||||
state as `host.json` (step 6). It writes the state to a file of its own
|
||||
and hard-links it in as `host.lock`. The link fails if the file exists,
|
||||
so of two hosts started at once, one gets it. If a live host holds the
|
||||
lock, or a live host started before `host.lock` existed holds
|
||||
`host.json`, the start refuses with exit 3: `a bus host already runs for
|
||||
<business> (pid <pid>)`. A lock whose host no longer runs is taken over
|
||||
whatever its age: it is moved aside, checked to be the file that was
|
||||
read, and removed; if another host's claim was moved aside in that race,
|
||||
it goes back. Each refusal below removes `host.lock` again, so a host
|
||||
that didn't start leaves no file.
|
||||
4. It forks `packages/bus/src/process.mjs` and waits up to 30 s for the boot
|
||||
reply. If the broker answers `{ok: false, error}`, the host exits 3 and
|
||||
prints `broker refused to start: <code>`. A timeout or an early exit
|
||||
gives exit 1.
|
||||
4. It forks `src/notifier-process.mjs` and hands it the reader capability
|
||||
5. It forks `src/notifier-process.mjs` and hands it the reader capability
|
||||
over IPC in `{op: 'start'}`. A notifier refusal closes the broker, and
|
||||
the host exits 3.
|
||||
5. It writes `<dataRoot>/bus-host/host.json` (0600): the pid, the process
|
||||
6. It writes `<dataRoot>/bus-host/host.json` (0600): the pid, the process
|
||||
start time, the business, the start time as text and the notifier
|
||||
binding. The file holds no capability.
|
||||
6. It starts the session launcher (`src/launcher.mjs`, "Sessions" below)
|
||||
binding. The file holds no capability. `bus stop`, `bus status` and the
|
||||
human commands' default business read it. It appears only once the
|
||||
broker and notifier are up, so a reader never finds a booting host with
|
||||
no broker socket.
|
||||
7. It starts the session launcher (`src/launcher.mjs`, "Sessions" below)
|
||||
and, with `--pm`, launches the business's `launch.by` instance. A PM
|
||||
launch that refuses closes the host with the refusal's exit code.
|
||||
|
||||
@@ -202,11 +216,11 @@ one, and the host stops with exit 1 for the unit to restart. A late reply
|
||||
never answers a later request, and a launch waiting on one refuses.
|
||||
|
||||
SIGTERM or SIGINT stops the notifier after its poll in flight, then closes
|
||||
the broker and removes `host.json`. If either child dies on its own, the
|
||||
host goes down with exit 1. The unit then restarts both. The host watches
|
||||
the children once both have started, and it checks each child's exit state
|
||||
at that point too, so a broker that dies while the notifier starts still
|
||||
takes the host down.
|
||||
the broker and removes `host.json`, then `host.lock`. If either child
|
||||
dies on its own, the host goes down with exit 1. The unit then restarts
|
||||
both. The host watches the children once both have started, and it
|
||||
checks each child's exit state at that point too, so a broker that dies
|
||||
while the notifier starts still takes the host down.
|
||||
|
||||
`bus stop` signals only a pid that still runs with the recorded start time
|
||||
and whose command line is `…/packages/cli/src/cli.mjs bus start`.
|
||||
@@ -360,7 +374,9 @@ A bundle file lives in `bus-host/` (0700) under a random name and is
|
||||
deleted on every path. On close the launcher answers `host-closing` to a
|
||||
connection still sending its request line, since nothing of it ran yet,
|
||||
and drops every other connection. It waits for any push in flight to finish
|
||||
under its lock before the broker stops.
|
||||
under its lock before the broker stops. It waits at most 2 s
|
||||
(`CLOSE_WAIT_MS`) for its `host-closing` answers to leave, then drops those
|
||||
connections too, so a peer that never reads can't hold the close.
|
||||
|
||||
### Trackers
|
||||
|
||||
|
||||
Reference in New Issue
Block a user