简体   繁体   中英

Why should we check WIFEXITED after wait in order to kill child processes in Linux system call?

I came across some code in C where we check the return value of wait and if it's not an error there's yet another check of WIFEXITED and WIFEXITSTATUS . Why isn't this redundant? As far as I understand wait returns -1 if an error occurred while WIFEXITED returns non-zero value if wait child terminated normally. So if there wasn't any error in this line if ( wait(&status) < 0 ) why would anything go wrong durng WIFEXITED check?

This is the code:

#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>

#define CHILDREN_NUM 5

int main () {

    int i, status, pid, p;
    for(i = 0; (( pid = fork() ) < 0) && i < CHILDREN_NUM;i++)
        sleep(5);


    if ( pid == 0 )
    {
        printf(" Child %d : successfully created!\n",i);
        exit( 0 );  /* Son normally exits here! */
    }

    p = CHILDREN_NUM;
    /* The father waits for agents to return succesfully */
    while ( p >= 1 )
    {
        if ( wait(&status) < 0 ) {
            perror("Error");
            exit(1);
        }

        if ( ! (WIFEXITED(status) && (WEXITSTATUS(status) == 0)) )  /* kill all running agents */
        {
            fprintf( stderr,"Child failed. Killing all running children.\n");
           //some code to kill children here
            exit(1);
        }
        p--;
    }

    return(0);
}

wait returning >= 0 tells you a child process has terminated (and that calling wait didn't fail), but it does not tell you whether that process terminated successfully or not (or if it was signalled).

But, here, looking at your code, it's fairly obvious the program does care about whether the child process that terminated did so successfully or not:

fprintf( stderr,"Child failed. Killing all running children.\\n");

So, the program needs to do further tests on the status structure that was populated by wait :

wait(&status) waits on the termination of a child process. The termination may be due to a voluntary exit or due to the receipt of an unhandled signal whose default disposition is to terminate the process.

WIFEXITED(status) and WIFSIGNALED(status) allow you to distinguish the two* cases, and you can later use either WEXITSTATUS or WTERMSIG to retrieve either the exit status ( if(WIFEXITED(status) ) or termination signal ( if(WIFSIGNALED(status) ).


*with waitpid and special flags ( WUNTRACED , WCONTINUED ), you can also wait on child process stops and resumptions, which you can detect with WIFSTOPPED or WIFCONTINUED (linux only) respectively. See waitpid(2) for more information.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM