mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
The runner spawns child agent sessions with `detached: true` (`cli/src/runner/run.ts:454`) so they survive runner restart, and runner cleanup (`run.ts:1049`) does not iterate or kill tracked children on shutdown. The runner is already designed as a long-lived process whose exit leaves agent sessions intact. But Node's `detached: true` calls `setsid()` (new process session), which does NOT escape the parent's systemd cgroup. Without an explicit `KillMode`, systemd defaults to `control-group`, which SIGTERMs every PID in the runner's cgroup whenever the unit stops - forcibly archiving every running session and discarding the detach contract. Adds `KillMode=process` to the reference runner unit and a note explaining the contract. With this change, `systemctl restart hapi-runner.service` (and any cascade-stop from `Requires=`) only signals the main runner PID; the cleanup runs without killing descendants; agent sessions stay alive; the new runner reconnects via the existing socket.io reconnect path (`cli/src/api/apiMachine.ts:385`) and re-establishes control via the existing RPC layer. This is the smallest fix for #915. The complementary safety net - runner re-attaching to orphaned children on cold start when no running runner exists - will be tracked in a separate issue and PR. AI-disclosure (per CONTRIBUTING.md): drafted with claude-opus-4.7 as peer agent during a fork-side post-mortem of a 7-hour outage that this fix would have prevented. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -536,6 +536,7 @@ After=network.target hapi-hub.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
KillMode=process
|
||||
ExecStart=/usr/local/bin/hapi runner start-sync
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
@@ -544,6 +545,8 @@ RestartSec=5
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
> **Why `KillMode=process`?** The runner spawns each agent session as a detached child process (`detached: true` in `cli/src/runner/run.ts`) so that sessions stay alive when the runner exits. Without `KillMode=process`, systemd's default `KillMode=control-group` sends SIGTERM to every PID in the runner's cgroup when the unit stops, defeating the detach and forcibly archiving every running session. `KillMode=process` preserves the contract: stopping or restarting the runner only signals the runner itself; agent sessions stay alive, and a fresh runner re-establishes control via the existing socket.io reconnect path. This applies to runner upgrades, manual restarts, and any reboot in which the runner unit is stopped before agents have finished.
|
||||
|
||||
Enable and start:
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user