Repository navigation
fix(gateway): preserve child turns during systemd drain - #140568
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: blocked before merge. Reviewed September 6, 2026, 9:21 PM ET / September 7, 2026, 01:21 UTC. ClawSweeper reviewWhat this changesThis PR lets Linux Gateway child processes finish during shutdown drain, reports incompatible service settings, and documents stopping database readers before recovery cleanup. Merge readiness⛔ Blocked before merge - 1 item remains The fix remains necessary: current main and v2026.9.2 still generate control-group shutdown behavior. No blocking defect was found in the introduced changes. Priority: P1 Review scores
Verification
How this fits togetherLinux systemd services supervise the Gateway and its child runtimes. Stop and restart requests must let the Gateway drain active work before systemd removes remaining processes. flowchart TD
A[Stop or restart request] --> B[systemd service]
B --> C[Signal Gateway first]
C --> D[Drain active child work]
D --> E[Gateway exits or deadline expires]
E --> F[Clean up remaining processes]
G[Doctor service audit] --> B
Before merge
Agent review detailsSecurityNone. PR surfaceSource -3, Tests +18, Docs +20. Total +35 across 10 files. View PR surface stats
Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Keep Gateway-owned drain, systemd-owned final cleanup, effective-setting diagnostics, and explicit profile-specific reinstall guidance for existing units. Do we have a high-confidence way to reproduce the issue? Yes for the supervisor defect: current-main service settings and systemd's documented signal behavior establish immediate child signaling during stop. This review did not execute a reproduction or establish the reporter's exact Codex exit sequence. Is this the best way to solve the issue? Yes. Using the supervisor's existing mixed mode is a narrow repair that preserves final cleanup; the cleanup documentation follows the reporter's accepted alternative without changing storage safeguards. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 0cd1ca7552a0. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
|
|
Merged via squash.
|
…137098 * commit '8a540c252002878f3c3e9d8dfb837b83c8602a78': (2210 commits) perf(plugins): keep bundled catalog lookups lightweight (#140597) refactor: streamline skills JSON serialization (#140581) fix(feishu): expand quoted merged-forward messages (#136231) fix(talk): keep opaque realtime routes out of public config (#129144) fix(ci): avoid Linux packaging on pull requests (#140589) fix(usage): release completed request payloads (#140588) fix(tooling): omit Trae machine squash credit (#140562) fix(ui): stop catalog paging in hidden tabs (#140583) fix(portals): reach IPv6 loopback with IPv4-only localhost records (#140580) fix(transcripts): preserve fixed and legacy capture history (#140563) fix(ui): prevent Talk E2E audio capture stalls (#138803) fix(media): release completed document source buffers (#140561) fix(anthropic): preserve resumed CLI caches across Git changes (#140566) chore(ui): refresh control ui locales (#140586) fix(ui): keep usage exports bound to their session instance (#140573) refactor(exa): test response readers through tool execution (#140572) fix(macos): omit incompatible worker binaries from app bundles (#140557) fix: avoid retaining discarded tool output (#140570) refactor(gateway): share placement move matching (#140569) fix(gateway): preserve child turns during systemd drain (#140568) ... # Conflicts: # .agents/skills/release-openclaw-maintainer/SKILL.md # docs/reference/RELEASING.md
) Keep child runtimes alive during cooperative drain while retaining final cgroup cleanup. Detect older effective unit settings and document explicit service repair. Clarify that recovery cleanup requires stopped database readers as well as writers. Addresses openclaw#140479 and openclaw#140467.
What Problem This Solves
Fixes an issue where a Linux managed Gateway restart interrupted an active child runtime before its advertised drain window finished (#140479, reported by @DonnieFi). Also documents the missing offline-reader prerequisite for recovery cleanup (#140467, reported by @agentzerodao); that reporter confirms main-session recovery succeeded after upgrading to 2026.9.2.
Related: #140479, #140467.
Why This Change Was Made
The generated systemd unit gave the Gateway 330 seconds to stop, but
KillMode=control-groupimmediately sent SIGTERM to its children as well.src/daemon/systemd-unit.tsnow usesmixed: the Gateway owns cooperative drain, and systemd retains final cgroup cleanup after parent exit or timeout.src/daemon/service-audit.tschecks the effective manager setting, including drop-ins, and flags older or omitted modes. Existing process/none diagnostic codes remain intact; duplicate dependency parsing is consolidated.Increasing the timeout cannot postpone that initial child signal. Process/none would abandon final descendant cleanup. Adding a separate Gateway-first stop protocol would duplicate lifecycle orchestration. The repair uses the supervisor's existing main-process-first contract instead.
Cleanup documentation explicitly requires session watchers and other database readers to stay stopped until cleanup exits, explains WAL/SHM changes, and gives the retry action. Unlike #140505, this does not relax destination verification or change persistence semantics. The issue's accepted documentation alternative preserves the existing deletion safeguards.
User Impact
New or explicitly reinstalled Linux units let child turns complete during Gateway drain. Existing installations need
openclaw gateway install --forcefor their selected profile; ordinary update-mode Doctor preserves existing Linux service definitions. Operator-owned drop-ins remain separately editable and are checked through their effective setting. Cleanup users can identify and stop readers that invalidate offline verification.Evidence
Reviewed head:
b1d9cde423b9dd70292fdb189f257624b6c7e740.pnpm check:changedpassed all gates, including core/core-test typechecks, three dead-export scans, lint and repository guards;git diff --checkpassed.tbx_01m1wpdp5yxrtq5zqf7gjp1sjastopped, wrapper exit 0. The synthetic timeout was shortened to two seconds; production remains 330 seconds. External Testbox cleanup may mark its backing Actions run cancelled; the wrapper records successful proof independently.The sibling Codex source was personally inspected at dependency revision
64b482500d00b331189beefd173a5e08b4060ff2:codex-rs/app-server/src/lib.rs:742-744disables graceful signal restart for stdio;:1040-1063exits on stdio closure;:1203-1212shuts down threads.codex-rs/app-server-transport/src/transport/stdio.rs:44-78translates stdin EOF to connection closure. Native systemd proof uses synthetic piped child work, not an authenticated provider or a reproduction of the reporter's exact clean-exit code.Production: +15/-18 (net -3). Tests: +23/-5 (net +18). Docs: +27/-7 (net +20). No new configuration, schema, persistence semantics, protocol, dependency, public SDK boundary, or changelog changes.
CI: exact-head run 34072463845 completed successfully on
b1d9cde423b9dd70292fdb189f257624b6c7e740, with no failed jobs. No contributor PR code was used; thanks to both issue reporters for the operational evidence.Review follow-through
ClawSweeper found no actionable source or security defect. Its remaining risk concerns independent access to the native evidence and the exact reported clean-exit signature. The mitigation is the implemented ownership boundary: Gateway drain, systemd final cleanup, effective-mode diagnostics, and explicit reinstall/drop-in guidance. The exact native Codex exit signature remains an explicit proof gap; an authenticated-provider replay is deferred because this patch changes the supervisor signal target and neither the provider nor stdio implementation. Detached-process kernel proof plus the existing Gateway process/recovery harnesses establishes the repaired boundary.
For direct inspection, the public dependency revision is available at Codex stdio signal handling and stdin closure. Availability was verified through the upstream commit API.
Sanitized observations from the completed native systemd 255 run:
The fixture asserted distinct parent/child session IDs and process groups. Final cleanup reported zero owned transient units and zero running observed process IDs, including the restart successor. The Testbox wrapper reported
exitCode=0,runStatus=succeeded, then stopped its lease. Its later external-portal synchronization warning did not change the proof result. These observations are synthetic process evidence; no claim about the reporter's exact exit code is added.