Understanding and Handling Zombie Processes in Linux
What is a zombie process?
A zombie process is a child process that has finished execution but still has an entry in the process table (state code Z, also shown as [defunct]). The process itself is no longer running — it consumes no CPU or memory — but its exit status has not been collected by the parent yet.
$ ps aux | grep Z
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND www-data 1234 0.0 0.0 0 0 ? Z 10:01 0:00 [defunct]
The Z in the STAT column identifies a zombie.
Why do zombie processes occur?
The root cause is a parent process that never calls wait() or waitpid() to collect the child's exit status.
When a process exits, the kernel stores its exit status in the process table and sends SIGCHLD to the parent. The entry stays there until the parent retrieves the status. If the parent never does, the child becomes a permanent zombie.
Common causes:
- Parent ignores
SIGCHLDwithout setting up auto-reaping - Parent has a bug in its signal handler
- Parent is stuck and cannot process signals
You cannot kill a zombie with kill -9 — the process is already dead. Only the parent (or its disappearance) can make a zombie disappear.
How to detect zombies
Find zombies and their parent
$ ps -el | grep Z
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 Z 1000 1234 1100 0 80 0 - 0 - pts/0 00:00:00 process
The PPID column gives you the parent's PID (1100 in this example). Confirm the parent with:
$ ps aux | awk 'NR==1 || $2==1100'
Monitor zombie count with top
$ top
Tasks: 142 total, 1 running, 141 sleeping, 0 stopped, 2 zombie
A steadily growing zombie count indicates an ongoing bug in a parent process.
How to fix zombie processes
Option 1: Signal the parent with SIGCHLD
If the parent can handle SIGCHLD, sending the signal may prompt it to call wait() and reap the zombie.
$ kill -SIGCHLD <PPID>
Option 2: Terminate the parent process
When the parent exits, the zombie's new parent becomes init (PID 1) or systemd, which reaps it immediately.
$ kill <PPID>
If the parent is unresponsive:
$ kill -9 <PPID>
Before force-killing a parent that is a service (nginx, mysqld, etc.), assess the impact on dependent connections and data integrity.
Option 3: Reboot the system
A last resort when zombies have accumulated to a level where normal operation is impaired. A reboot reinitializes the process table.
Are zombie processes dangerous?
A handful of zombies cause no real harm. They consume neither CPU nor memory.
However, they become a problem at scale:
- PID exhaustion: Linux's default PID ceiling (
/proc/sys/kernel/pid_max) is 32,768. If zombies accumulate, available PIDs run out and no new processes can start. - Process table pressure: Each entry consumes a small amount of kernel memory.
Check your current PID limit:
$ cat /proc/sys/kernel/pid_max 32768
Preventing zombie processes in application code
Zombies are a symptom of a bug in the parent application. The real fix belongs in the code.
- Call
waitpid(-1, NULL, WNOHANG)in a loop inside aSIGCHLDhandler - Use the double fork technique to orphan the grandchild under
init - Set
SIGCHLDtoSIG_IGN— POSIX-compliant systems then auto-reap children