Objective: Analyse how zombie processes or defunct processes are created and how to remove them from the process table.
A zombie process or defunct process is a process that has completed execution but still has an entry in the process table. This occurs for child processes that has been forked by a parent process using the fork()
system call but not reaped by the parent process using the wait()
system call.
The parent process has to make a wait()
(or waitpid()
) system call to get the exit status of the child process once the child process has terminated. If the wait()
call is not performed by the parent process, the child process will become a zombie process.
A SIGCHLD
signal is sent to the parent process whenever a child process terminates. The parent process needs to have a SIGCHLD
signal handler function defined with a call to wait()
– this will remove the child process from the process table.
To remove zombie processes from a system, the SIGCHLD
signal can be sent to the parent manually, using the kill
command. If the parent process still refuses to reap the zombie process, and if the parent process can be killed, the next step is to kill the parent process. When a child process loses its parent process, init
(PID 1) becomes its new parent. init
periodically executes the wait()
system call to reap any zombie processes with init
as parent.
I wrote a simple C program to create a zombie process.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <errno.h> int main () { pid_t child_pid; int child_status; child_pid = fork (); if (child_pid > 0) { // parent process will sleep for 30 seconds and exit, without a call to wait() fprintf(stderr,"parent process - %d\n", getpid()); sleep(30); exit(0); } else if (child_pid == 0) { // child process will exit immediately fprintf(stderr,"child process - %d\n", getpid()); exit(0); } else if (child_pid == -1) { // fork() error perror("fork() call failed"); exit (-1); } else { // this should not happen fprintf(stderr, "unknown return value of %d from fork() call", child_pid); exit (-2); } return 0; } |
Save the above code as zombie.c
and compile it using gcc
.
1 |
$ gcc zombie.c -o zombie |
Next, run the program.
1 2 3 |
$ ./zombie parent process - 26570 child process - 26571 |
From another terminal, do a ps
to display running processes. You will see a zombie process.
1 2 3 |
$ ps -ef | grep zombie ibrahim 26570 22886 0 15:59 pts/2 00:00:00 ./zombie ibrahim 26571 26570 0 15:59 pts/2 00:00:00 [zombie] <defunct> |
Once the parent process has terminated (after 30 seconds), the zombie process will be removed from the process table by the init
process.