GPT on Question 14, Sep 21
I'm writing a bash script to purge orphaned children after the parent dies. What's the idiomatic way?There is no fully reliable “after the parent dies” mechanism in portable Bash. Orphans are immediately reparented, and an EXIT trap cannot run if the script receives SIGKILL or crashes.
The usual pattern is:
- 1.Run children in a dedicated process group/session.
- 2.Trap normal exit and catchable signals.
- 3.Kill the entire child process group, not just the immediate child.
#!/usr/bin/env bash
set -Eeuo pipefail
setsid my_worker --arg foo &
worker_pgid=$!
cleanup() {
trap - EXIT INT TERM HUP
# Negative PID means “signal this process group”.
kill -TERM -- "-$worker_pgid" 2>/dev/null || true
# Optional grace period, then force termination.
sleep 2
kill -KILL -- "-$worker_pgid" 2>/dev/null || true
wait "$worker_pgid" 2>/dev/null || true
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
trap 'exit 129' HUP
wait "$worker_pgid"Avoid relying on pkill -P "$$": it only finds current direct children and is vulnerable to children forking or being reparented.
If cleanup must also happen when the parent is killed with SIGKILL, Bash alone cannot guarantee it. Use one of:
- •systemd service/scope with
KillMode=control-group - •a container or cgroup supervisor
- •Linux
prctl(PR_SET_PDEATHSIG, SIGTERM)in the child, usually via a small wrapper - •a dedicated watchdog/supervisor
For production services, a supervisor/cgroup is generally the idiomatic and most reliable solution.
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-09-21 09:06:35 UTC
- Run
- 20260921T090021Z-989a7c
- Served by
- OpenAI · HTTP 200 · finish stop
- Size
- 1,457 characters · 898 tokens out incl. hidden reasoning · 23.8 s
There is no fully reliable “after the parent dies” mechanism in portable Bash. Orphans are immediately reparented, and an `EXIT` trap cannot run if the script receives `SIGKILL` or crashes.
The usual pattern is:
1. Run children in a dedicated process group/session.
2. Trap normal exit and catchable signals.
3. Kill the entire child process group, not just the immediate child.
```bash
#!/usr/bin/env bash
set -Eeuo pipefail
setsid my_worker --arg foo &
worker_pgid=$!
cleanup() {
trap - EXIT INT TERM HUP
# Negative PID means “signal this process group”.
kill -TERM -- "-$worker_pgid" 2>/dev/null || true
# Optional grace period, then force termination.
sleep 2
kill -KILL -- "-$worker_pgid" 2>/dev/null || true
wait "$worker_pgid" 2>/dev/null || true
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
trap 'exit 129' HUP
wait "$worker_pgid"
```
Avoid relying on `pkill -P "$$"`: it only finds current direct children and is vulnerable to children forking or being reparented.
If cleanup must also happen when the parent is killed with `SIGKILL`, Bash alone cannot guarantee it. Use one of:
- **systemd service/scope** with `KillMode=control-group`
- a container or cgroup supervisor
- Linux `prctl(PR_SET_PDEATHSIG, SIGTERM)` in the child, usually via a small wrapper
- a dedicated watchdog/supervisor
For production services, a supervisor/cgroup is generally the idiomatic and most reliable solution.
End of response · 46 lines · 1,457 characters · sha256 03fb1123bc66dbd989329b612c2049213c3cb75a7d43af08e5136ccef47297f5