MODELDRIFT.WATCH

Question 13 · Sep 30 · Day 21

Claude on Question 13, Sep 30

How do I kill a zombie process in Linux that won't respond to SIGTERM?

First, the key insight

A zombie process is already dead. Signals have no effect on it because there's no running process to receive them — no code, no address space, no thread of execution. All that remains is an entry in the process table holding the exit status, waiting for the parent to collect it via wait()/waitpid().

So kill -9 on a zombie does nothing. This is expected, not a broken system.

Confirm it's actually a zombie

ps -eo pid,ppid,stat,cmd | awk '$3 ~ /^Z/'

State Z (often shown as <defunct>) means zombie. If you instead see state D, that's uninterruptible sleep — a genuinely different problem, usually a process blocked on I/O (dead NFS mount, failing disk, buggy driver). Those also ignore signals but the fix is unblocking the I/O, not reaping.

Getting rid of it

Note the PPID from the output above. The parent is the one misbehaving.

Nudge the parent to reap:

kill -s SIGCHLD <PPID>

This works if the parent has a SIGCHLD handler but somehow missed the notification. Often it does nothing, because the parent simply never calls wait() at all.

Kill or restart the parent:

kill <PPID>          # try graceful first
kill -9 <PPID>       # if it won't exit

When the parent dies, the zombie is re-parented to PID 1 (systemd or init), which reaps orphans immediately. The zombie disappears.

If the parent is a service, prefer systemctl restart <service> so it comes back cleanly.

Does it matter?

Usually not much. Each zombie consumes one PID slot and a tiny kernel structure — no memory, no CPU. A handful is cosmetic.

It matters when zombies accumulate, since they can exhaust the PID space (cat /proc/sys/kernel/pid_max, typically 32768 or 4194304 on newer kernels). That's a symptom of a parent that forks without reaping, and the real fix is in that program:

signal(SIGCHLD, SIG_IGN);  /* let the kernel auto-reap */

or a proper waitpid(-1, &status, WNOHANG) loop in a SIGCHLD handler.

Containers

A very common source of zombies. If your container's PID 1 is your application rather than a real init, it inherits orphans but never reaps them. Fix with:

docker run --init ...

or bake in tini / dumb-init as the entrypoint.

sha256 12dd3ea257fc… · 33 tokens in · 1,564 out · 20.9 s · via Claude Platform on AWS · stopped on its own

Sep 30, the whole dayQuestion 13, every day

Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
Model
anthropic/claude-opus-5
pinned anthropic/claude-opus-5-20260723; alias resolved to anthropic/claude-opus-5-20260723 at 2026-09-30 09:00:07 UTC (matches the pin)
Date
2026-09-30 · run 20260930T090007Z-45ce12 · scorer v1
Scored
answered
sha256
12dd3ea257fc7c64aa02e04d8a522c76f27ecd1610f7fe4db7b8d5019677ef9c
Permalink
https://modeldrift.watch/r/2026-09-30/R1/anthropic/claude-opus-5/
Scored
answered
Received
2026-09-30 09:05:34 UTC
Run
20260930T090007Z-45ce12
Served by
Claude Platform on AWS · HTTP 200 · finish stop
Size
2,285 characters · 1,564 tokens out incl. hidden reasoning · 20.9 s
## First, the key insight
A zombie process is **already dead**. Signals have no effect on it because there's no running process to receive them — no code, no address space, no thread of execution. All that remains is an entry in the process table holding the exit status, waiting for the parent to collect it via `wait()`/`waitpid()`.
So `kill -9` on a zombie does nothing. This is expected, not a broken system.
## Confirm it's actually a zombie
```bash
ps -eo pid,ppid,stat,cmd | awk '$3 ~ /^Z/'
```
State `Z` (often shown as `<defunct>`) means zombie. If you instead see state `D`, that's uninterruptible sleep — a genuinely different problem, usually a process blocked on I/O (dead NFS mount, failing disk, buggy driver). Those also ignore signals but the fix is unblocking the I/O, not reaping.
## Getting rid of it
Note the **PPID** from the output above. The parent is the one misbehaving.
**Nudge the parent to reap:**
```bash
kill -s SIGCHLD <PPID>
```
This works if the parent has a `SIGCHLD` handler but somehow missed the notification. Often it does nothing, because the parent simply never calls `wait()` at all.
**Kill or restart the parent:**
```bash
kill <PPID> # try graceful first
kill -9 <PPID> # if it won't exit
```
When the parent dies, the zombie is re-parented to PID 1 (`systemd` or `init`), which reaps orphans immediately. The zombie disappears.
If the parent is a service, prefer `systemctl restart <service>` so it comes back cleanly.
## Does it matter?
Usually not much. Each zombie consumes one PID slot and a tiny kernel structure — no memory, no CPU. A handful is cosmetic.
It matters when zombies **accumulate**, since they can exhaust the PID space (`cat /proc/sys/kernel/pid_max`, typically 32768 or 4194304 on newer kernels). That's a symptom of a parent that forks without reaping, and the real fix is in that program:
```c
signal(SIGCHLD, SIG_IGN); /* let the kernel auto-reap */
```
or a proper `waitpid(-1, &status, WNOHANG)` loop in a `SIGCHLD` handler.
## Containers
A very common source of zombies. If your container's PID 1 is your application rather than a real init, it inherits orphans but never reaps them. Fix with:
```bash
docker run --init ...
```
or bake in `tini` / `dumb-init` as the entrypoint.

End of response · 54 lines · 2,285 characters · sha256 12dd3ea257fc7c64aa02e04d8a522c76f27ecd1610f7fe4db7b8d5019677ef9c