1. Overview

In this tutorial, we’ll learn about zombie processes and ways to clean them. First, we’ll understand the various process states. Then, we’ll check ways to identify the zombie processes. Finally, we’ll arrive at solutions to our problem.

2. What Is a Zombie Process

Zombie processes in Linux are sometimes also referred to as defunct or dead processes. They’re processes that have completed their execution, but their entries are not removed from the process table.

2.1. Process States

Linux maintains a process table of all the processes running, along with their states. Let’s briefly overview the various process states:

  1. Running (R): These processes are currently running or runnable.
  2. Waiting (S/D): These are the processes that are waiting for an event or a resource. The wait can either be an interruptible sleep (S) or an uninterruptible sleep (D).
  3. Stopped (T): We can stop a Linux process by sending an appropriate signal.
  4. Zombie (Z): When a process finishes its task, it releases the system resources it was using and cleans up its memory. However, its entry from the process table is not removed, and its status is set as EXIT_ZOMBIE.

We’ll gain a better understanding of the concept of zombie processes in the next subsections.

2.2. Creation of Zombie Processes

When a process completes its job, the Linux kernel notifies the exiting process’s parent by sending the SIGCHLD signal. The parent then executes the wait() system call to read the status of the child process and reads its exit code. This also cleans up the entry of the child process from the process table, and hence, the process finishes.

However, if a parent process isn’t programmed to execute the wait() system call on the creation of the child process, proper cleanup doesn’t happen. In such cases, the parent process cannot monitor the state changes of the child processes, and eventually, it ignores the SIGCHLD signal. This causes the zombie state of the finished process to stay in the process table, and hence it appears in the process list as a zombie process.

Another case of interest is when a parent process is unable to handle or receive the SIGCHLD signal from the child process. Such cases also lead to zombie creation.

2.3. Identification of Zombie Processes

We can identify the list of zombies using the ps command:

$ ps ux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
shubh        9  0.0  0.0  16916  2760 tty1     S    Dec19   0:00 /bin/bash --login
shubh      108  0.0  0.0      0     0 tty1     Z    16:25   0:00 [zombie] <defunct> 
shubh      109  0.0  0.0  17384  1928 tty2     R    16:25   0:00 ps ux

As observed from the output, the Z in the STAT column or zombie or <defunct> pattern from the output of the ps command can be used to identify the zombies.

Let’s further filter the output based on the Z process state using the awk command:

$ ps ux | awk '{if($8=="Z") print}'
shubh       108  0.0  0.0      0     0 tty1     Z    16:25   0:00 [zombie] <defunct>

Another convenient method for checking the number and list of zombie processes is to use the top command:

$ top
Tasks:   8 total,   1 running,   6 sleeping,   0 stopped,   1 zombie
%Cpu(s):  0.7 us,  1.6 sy,  0.0 ni, 96.5 id,  0.0 wa,  1.2 hi,  0.0 si,  0.0 st
KiB Mem :  8269412 total,  3161228 free,  4878832 used,   229352 buff/cache
KiB Swap: 15483260 total, 14830144 free,   653116 used.  3256848 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    1 root      20   0    8936    192    148 S   0.0  0.0   0:00.17 init
    8 root      20   0    8936     96     56 S   0.0  0.0   0:00.00 init
    9 shubh     20   0   16916   2748   2640 S   0.0  0.0   0:00.43 bash
   76 root      20   0    8936    224    184 S   0.0  0.0   0:00.00 init
   77 shubh     20   0   16784   3432   3332 S   0.0  0.0   0:00.35 bash
  161 shubh     20   0       0      0      0 Z   0.0  0.0   0:00.00 zombie
  162 shubh     20   0   17624   2084   1508 R   0.0  0.0   0:00.00 top

Here, along with the other details, we can also see the number of zombie processes in the summary at the top of the output.

3. Cleaning a Zombie Process

We can’t really kill a zombie process since it’s already dead. However, there are a few workarounds we can use to clean up a zombie process.

3.1. Using SIGCHLD Signal

We can manually send the SIGCHLD signal to the parent of a zombie process. Consequently, it will intimate the parent to trigger the wait() system call, which will clean up the defunct child process from the process table.

Let’s find the parent id of our defunct process:

$ ps -A -ostat,pid,ppid | grep -e '[zZ]'
Z      108   103

This lists the STAT column, process id, and parent process id of zombie processes. Next, let’s send the SIGCHLD signal to the parent process using the kill command:

kill -s SIGCHLD 103

However, it isn’t really guaranteed that sending the SIGCHLD signal to the parent will kill a zombie process. It works only in cases where parent processes can handle the SIGCHLD signals.

3.2. Killing the Parent Process

If the method discussed in the previous section is unable to clear the defunct process, we should consider killing its parent process:

kill -9 103

Here, 103 is the parent id of our defunct process with PID 108.

However, killing a parent can affect all its child processes. Hence, we should exercise extra caution and must identify the impact before killing a parent process.

If a lot of zombie processes are present, or if the parent of the zombie process is the init process (with pid=1), we can also consider a system reboot to get rid of the defunct processes.

4. Conclusion

In this tutorial, we studied methods to clean up a zombie process.

In the beginning, we discussed the various process states in Linux. Then, we examined the situations that can lead to the creation of a zombie process. Next, we saw different ways to find zombie processes in our system. Finally, we discussed the solutions to our problem.

guest
0 Comments
Inline Feedbacks
View all comments