Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically check for zombie child process in Linux using C

I have written a simple C program in RedHat Linux which waits for a child process using waitpid after calling execv.

int main( int argc, char * argv[] )
{
    int pid;
    int status = 0;
    int wait_ret;

    const char * process_path = argv[1];

    if ( argc < 2 )
    {
        exit( EXIT_FAILURE );
    }

    pid = fork(); //spawn child process

    if ( 0 == pid ) //child
    {
        int ret = execv( process_path, &argv[1] );

        if ( ret )
        {
            printf( "execv failed: %s\n", strerror( errno ) );
        }

        exit( EXIT_SUCCESS );
    }

    //wait for the child to terminate
    wait_ret = waitpid( pid, &status, WUNTRACED );

    if ( -1 == wait_ret )
    {
        printf( "ERROR: Failed to wait for process termination\n" );
        exit( EXIT_FAILURE );
    }

    // ... handlers for child exit status ...

    return 0;
}

I am using this as a simple watchdog for some processes I am runnning.

My problem is that one process in particular is not being reaped by waitpid upon exiting and instead remains forever in a Zombie state while waitpid is hung. I am not sure why waitpid is unable to reap this process once it becomes a Zombie (maybe a leaked file descriptor or something).

I could use the WNOHANG flag and poll the child's stat proc file to check for the Zombie state but I would prefer a more elegant solution. Maybe there is some function that I could use to get the Zombie status from without polling this file?

Does anyone know an alternative to waitpid which WILL return when the process becomes a Zombie?

Additional Information:

The child process is being closed by a call to exit( EXIT_FAILURE); in one of its threads.

cat /proc/<CHILD_PID>/stat (before exit):

1037 (my_program) S 1035 58 58 0 -1 4194560 1309 0 22 0 445 1749 0 0 20 0 13 0 4399 22347776 1136 4294967295 3336716288 3338455332 3472776112 3472775232 3335760920 0 0 4 31850 4294967295 0 0 17 0 0 0 26 0 0 3338489412 3338507560 3338600448

cat /proc/<CHILD_PID>/stat (after exit):

1037 (my_program) Z 1035 58 58 0 -1 4227340 1316 0 22 0 464 1834 0 0 20 0 2 0 4399 0 0 4294967295 0 0 0 0 0 0 0 4 31850 4294967295 0 0 17 0 0 0 26 0 0 0 0 0

Note that the child PID is 1037 and the parent PID is 1035 in this case.

like image 943
Nathan Owen Avatar asked Aug 16 '26 11:08

Nathan Owen


1 Answers

Any process that terminates becomes a zombie until it is collected by a wait call. Here the wait does not seem to happen in all cases.

From the code given I can't figure out why the wait does not happen and the process remains a zombie. (not without running it anyway)

But instead of waiting on a specific pid only, you can wait on any child by using -1 as the first argument to waitpid. Don't use WNOHANG, as it require busy polling (don't do that).

You may also want to drop WUNTRACED unless you have a specific reason to include it. But there is no harm in dropping it and see what difference it makes.

like image 187
koder Avatar answered Aug 18 '26 02:08

koder



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!