How To Kill A Zombie

I mean, a zombie process of course. Normally, this should not happen, but will happen if a parent process fails to run waitpid() to wait for child process to finish. I came across this situation many times, but never was able to tell how to fix it quickly and without restarting everything. From my understanding, zombies don’t hold onto any open files or memory, they are simply a record in the process table, which could be annoying. I’ve done a bit of research myself and found that somebody mentioned that it is possible to forcibly invoke waitpid() as a parent process using gdb. Let’s try! Here’s a quick C program to create a zombie process:

#include <stdio.h>
#include <unistd.h>

int main() {
  pid_t child = fork();
  int cnt = 0;
  if ( child  > 0) {
    pid_t parent = getpid();
    printf("Parent: %i, child is: %i\n", parent, child);
    printf("To terminate zombie process, use: sudo gdb -p %i --batch -ex \"call waitpid(%i,0,0)\"\n", parent, child); 
    for(;;) {
      printf("Iteration: %i\n", cnt++);
  } else {
    printf("Child: %i\n", getpid());
    printf("Check for zombies!\n");

Let’s run it:

$ ./a.out 
Parent: 14550, child is: 14551
Child: 14551
To terminate zombie process, use: sudo gdb -p 14550 --batch -ex "call waitpid(14551,0,0)"
Check for zombies!
Iteration: 0
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
Iteration: 5

Here is our zombie:

$ ps aux|grep defunct
eugene   14551  0.0  0.0      0     0 pts/12   Z+   15:21   0:00 [a.out] <defunct>

Running gdb to invoke waitpid():

$ sudo gdb -p 14550 --batch -ex "call waitpid(14551,0,0)"
0xb76ebcb0 in ?? ()
$1 = 14551

And check for zombies again, nothing there:

$ ps aux|grep defunct
eugene   14561  0.0  0.0   4700  2068 pts/13   S+   15:21   0:00 grep --colour=auto defunct

It is very important to mention that when attached to a process with gdb, the process is stopped and will continue running after detaching. In batch mode, gdb will auto-detach.

comments powered by Disqus