GPT on Question 14, Oct 3
I'm writing a bash script to purge orphaned children after the parent dies. What's the idiomatic way?A Bash process cannot reliably clean up children after it has died. The usual pattern is to track child PIDs and kill/reap them from an EXIT trap:
#!/usr/bin/env bash
children=()
cleanup() {
status=$?
trap - EXIT INT TERM HUP
if ((${#children[@]})); then
kill -TERM "${children[@]}" 2>/dev/null || true
wait "${children[@]}" 2>/dev/null || true
fi
exit "$status"
}
trap cleanup EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM
some_command &
children+=("$!")
another_command &
children+=("$!")
waitImportant limitations:
- •This handles normal exit and catchable signals, but not
SIGKILL, power loss, or a hard crash. - •It kills only the recorded direct children. If they spawn descendants, use a dedicated process group/session and terminate the group:
setsid some_command &
group_leader=$!
cleanup() {
status=$?
trap - EXIT INT TERM HUP
kill -TERM -- "-$group_leader" 2>/dev/null || true
wait "$group_leader" 2>/dev/null || true
exit "$status"
}Avoid blindly using kill 0; it can kill unrelated processes in the script’s process group.
For guaranteed cleanup of an entire process tree, including when the script gets SIGKILL, use an external supervisor such as systemd with a dedicated cgroup (KillMode=control-group), a container runtime, or—on Linux—a small wrapper using prctl(PR_SET_PDEATHSIG, ...).
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-10-03 09:05:29 UTC
- Run
- 20261003T090008Z-b2d35e
- Served by
- OpenAI · HTTP 200 · finish stop
- Size
- 1,438 characters · 893 tokens out incl. hidden reasoning · 11.8 s
A Bash process cannot reliably clean up children **after it has died**. The usual pattern is to track child PIDs and kill/reap them from an `EXIT` trap:
```bash
#!/usr/bin/env bash
children=()
cleanup() {
status=$?
trap - EXIT INT TERM HUP
if ((${#children[@]})); then
kill -TERM "${children[@]}" 2>/dev/null || true
wait "${children[@]}" 2>/dev/null || true
fi
exit "$status"
}
trap cleanup EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM
some_command &
children+=("$!")
another_command &
children+=("$!")
wait
```
Important limitations:
- This handles normal exit and catchable signals, but not `SIGKILL`, power loss, or a hard crash.
- It kills only the recorded direct children. If they spawn descendants, use a dedicated process group/session and terminate the group:
```bash
setsid some_command &
group_leader=$!
cleanup() {
status=$?
trap - EXIT INT TERM HUP
kill -TERM -- "-$group_leader" 2>/dev/null || true
wait "$group_leader" 2>/dev/null || true
exit "$status"
}
```
Avoid blindly using `kill 0`; it can kill unrelated processes in the script’s process group.
For guaranteed cleanup of an entire process tree, including when the script gets `SIGKILL`, use an external supervisor such as **systemd** with a dedicated cgroup (`KillMode=control-group`), a container runtime, or—on Linux—a small wrapper using `prctl(PR_SET_PDEATHSIG, ...)`.
End of response · 54 lines · 1,438 characters · sha256 c3857f084df53bd778819a0118612024eb4c2669baa3169bb2dcf9e2401b7849