Can this C code create zombie processes?

mgus picture mgus · Dec 15, 2013 · Viewed 7.9k times · Source

I am wondering if the following code can create zombies:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(){
    int i=1;
    pid_t p;
    p = fork();
    i++;
    if(p!=0){
        waitpid(p, NULL, 0);
    }
    printf("%d\n",i);
    return 0;
}

So, the parent process calls the waitpid for the child process, which returns immediately if the child has not already exited. So, no zombies can arise so far. But, if the child exits before

return 0;
command this would be a zombie then? I am actually confused about it. Should the waitpid be the last line of code before the program terminates? Any help would be appreciated. Thanks!

Answer

alk picture alk · Dec 15, 2013

The child only becomes a zombie if it ends and the parent doesn't call wait*() as long as itself lives on.

In the moment the parent also ends the child is reaped by the init process which will take care to call wait*() on the child, so it will finally end and with this leave the zombie state and disappears from the process list.

To provoke the child created in your example code to become a zombie modify the code for example as follows:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void) 
{
    pid_t p = fork();

    if (p != 0) 
    {
        waitpid(p, NULL, 0); /* See if the child already had ended. */
        sleep(1); /* Wait 1 seconds for the child to end. And eat away the SIGCHLD in case if arrived. */
        pause(); /* Suspend main task. */
    }
    else
    {
        sleep(3); /* Just let the child live for some tme before becoming a zombie. */
    }

    return 0;
}

Due to the two following facts:

  • the child sleeps for 3s so the parent's call to waitpid() most probably will always fail
  • the default handling of SIGCHLD is to ignrore it.

the code above in fact is the same as:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void) 
{
    pid_t p = fork();

    if (p != 0) 
    {
        pause(); /* Suspend main task. */
    }
    else
    {
        sleep(3); /* Just let the child live for some tme before becoming a zombie. */
    }

    return 0;
}