#20629: fix: use KillMode=mixed to prevent orphaned child processes
gateway
size: XS
## Summary
- Changes the systemd unit's `KillMode` from `process` to `mixed` to prevent orphaned child processes from accumulating across gateway restarts
## Problem
When the gateway service restarts, `KillMode=process` only sends SIGTERM to the main process. Child processes (health checks, plugins, doctor) survive in the cgroup and continue running indefinitely. On long-running instances, this leaks hundreds of MB of RAM.
**Observed on a t3.medium (4 GB) instance after 2 days:**
| Process | RSS |
|---------|-----|
| clawdbot (health check) | 197 MB |
| clawdbot-plugins | 182 MB |
| clawdbot-doctor | 134 MB |
| clawdbot-plugins (2nd) | 106 MB |
| **Total orphans** | **618 MB** |
## Fix
`KillMode=mixed` sends SIGTERM to the main process first (allowing graceful shutdown), then SIGKILL to any remaining children after `TimeoutStopSec`. This:
- Prevents orphaned child processes from accumulating
- Still allows the main gateway process to shut down gracefully
- Is the recommended mode for services that spawn children that should not outlive the parent
The original `KillMode=process` was added to avoid killing podman's `conmon` process, but `mixed` achieves the same goal — `conmon` (as a direct child of `ExecStart`) would receive SIGTERM and can handle it gracefully, while truly orphaned processes get cleaned up.
## Test plan
- [ ] Verify gateway starts normally with `KillMode=mixed`
- [ ] Restart the gateway service and confirm child processes are terminated
- [ ] Confirm no orphaned health-check/plugin/doctor processes after multiple restarts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Changes systemd `KillMode` from `process` to `mixed` to prevent orphaned child processes (health checks, plugins, doctor) from accumulating across gateway restarts, addressing a memory leak issue.
- Prevents orphaned child processes from surviving gateway restarts
- Allows graceful shutdown of main process via SIGTERM before SIGKILL cleanup
- Addresses memory leak where orphaned processes accumulated hundreds of MB over time
- Comment mentions `TimeoutStopSec` but the directive isn't actually configured (defaults to 90s)
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge with minimal risk
- The change from `KillMode=process` to `KillMode=mixed` is technically sound and addresses a real memory leak issue. The approach is standard for systemd services that spawn child processes. However, `TimeoutStopSec` is referenced in comments but not configured, relying on the default 90-second timeout. Adding an explicit timeout value would make the behavior more predictable.
- No files require special attention
<sub>Last reviewed commit: 499790a</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#20357: feat(gateway): make systemd KillMode configurable for gateway install
by Jackten · 2026-02-18
80.8%
#13084: fix(daemon): multi-layer defense against zombie gateway processes
by openperf · 2026-02-10
78.1%
#11147: fix(daemon): stop gateway by port when no daemon service is active
by jasonthewhale · 2026-02-07
76.4%
#9036: fix: add systemd restart limits to prevent infinite crash-loops
by joetomasone · 2026-02-04
76.3%
#16845: fix(daemon): gateway auto-restart on SIGTERM + agent restart guidel...
by kiminbean · 2026-02-15
75.1%
#7155: fix(gateway): use kill SIGTERM instead of bootout for stop
by rafaelreis-r · 2026-02-02
74.5%
#23666: fix(doctor): openclaw-browser.service falsely flagged as duplicate ...
by yinghaosang · 2026-02-22
74.3%
#14259: fix(discord): add timeout to restart to prevent duplicate responses
by George5562 · 2026-02-11
73.4%
#9460: fix(gateway): clean up lock file on service stop
by zenchantlive · 2026-02-05
73.2%
#16016: fix: update systemd unit version on gateway restart
by jbold · 2026-02-14
73.0%