Claude on Question 13, Sep 21
How do I kill a zombie process in Linux that won't respond to SIGTERM?The short answer: you can't kill a zombie
A zombie (state Z, also shown as defunct) is a process that has already terminated. Its memory, file descriptors, and threads are all gone. What remains is a small entry in the kernel's process table holding its exit status, waiting for the parent to collect it via wait()/waitpid().
Signals are delivered to running code. A zombie has no code to run, so SIGTERM, SIGKILL, SIGCONT — none of them do anything. This is expected behavior, not a stuck process.
Find the zombie and its parent
ps -eo pid,ppid,stat,comm | awk '$3 ~ /^Z/'
Or to see the whole tree:
ps -ef --forest | grep -A5 defunct
The PPID column is what matters — that's the negligent parent.
Fix it
1. Nudge the parent to reap:
kill -CHLD <PPID>
This sometimes works if the parent has a SIGCHLD handler but missed the original notification. Usually it won't help, since the common cause is a parent with no handler at all.
2. Kill the parent:
kill <PPID> # try graceful first kill -9 <PPID> # if it ignores SIGTERM
When the parent dies, the zombie is re-parented to PID 1 (systemd or init), which reaps orphans immediately. The zombie vanishes.
If the parent is a service, prefer restarting it properly:
systemctl restart <service>
3. If the parent is PID 1 — that's a genuine bug in systemd or your container's init. Zombies accumulating under PID 1 usually means you're running a container with a non-reaping init (e.g. a shell script or app as PID 1). Use --init with Docker, or tini/dumb-init as the entrypoint.
Do you actually need to?
A handful of zombies is harmless. Each one costs a PID slot and a few hundred bytes of kernel memory. Check your budget:
cat /proc/sys/kernel/pid_max # usually 32768 or 4194304 ps -eo stat | grep -c '^Z' # current zombie count
The problem is only real if a leaking parent is generating zombies continuously and will eventually exhaust PIDs. In that case, fixing the parent matters more than clearing the current batch.
Are you sure it's a zombie?
People often conflate zombies with uninterruptible sleep (state D), which genuinely doesn't respond to SIGKILL and does hold resources. Those are typically blocked on I/O — a hung NFS mount, a failing disk, a stuck kernel driver.
ps -eo pid,stat,wchan:30,comm | awk '$2 ~ /^D/'
The wchan column shows the kernel function it's blocked in, which usually points at the culprit. D-state processes can't be killed at all; you have to clear the underlying I/O condition (e.g. umount -f -l a dead NFS mount) or reboot.
Preventing it in your own code
If you're writing the parent, pick one:
signal(SIGCHLD, SIG_IGN); // kernel auto-reaps, exit statuses discarded
// or handle it properly
void reaper(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0);
}
signal(SIGCHLD, reaper);The while loop matters — signals aren't queued, so one SIGCHLD can represent several dead children.
In shell scripts, wait after backgrounding jobs. In Python, use subprocess and call .wait() or .poll(), or let multiprocessing handle it.
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-09-21 09:05:57 UTC
- Run
- 20260921T090021Z-989a7c
- Served by
- Claude Platform on AWS · HTTP 200 · finish stop
- Size
- 3,265 characters · 1,860 tokens out incl. hidden reasoning · 25.8 s
End of response · 87 lines · 3,265 characters · sha256 d80399865bf8cab72bbd5a9a75ac36c35b88da189edbda36da8ae64210919439