Search code examples
cforkexit-code

Return from exit() with fork() is weirdly bitshifted


I have a code in C that forks itself sometimes, each fork does something then returns an error code. Currently, each child process returns its ID (0..n).

void other(int numero){
    ...
    exit(numero);
}

int main(...){
    for(int i = 0; i < 6; i++){
        if(fork() == 0){
            other(i);
        }
    }
    int order[6];
    for(int i = 0; i < 6; i++){
        int code;
        waitpid(0, &code, 0);
        order[i] = code; // <-- HERE
    }
}

Weirdly, this returns a multiple of the real value. By replacing the line I marked with :

order[i] = code >> 8;

I managed to get the expected result of 0..5. However, I really don't understand why this happens. I expect it's because of some kind of type problem, but I don't see it, I'm always using ints.


Solution

  • The correct replacement for order[i] = code; is order[i] = WEXITSTATUS(code); Also, note that waitpid can return even if the process didn't exit; you should use WIFEXITED to make sure it did.

    From man 2 waitpid:

       If wstatus is not NULL, wait() and waitpid() store status information
       in the int to which it points.  This integer can be inspected with
       the following macros (which take the integer itself as an argument,
       not a pointer to it, as is done in wait() and waitpid()!):
    
        WEXITSTATUS(wstatus)
              returns the exit status of the child.  This consists of the
              least significant 8 bits of the status argument that the child
              specified in a call to exit(3) or _exit(2) or as the argument
              for a return statement in main().  This macro should be
              employed only if WIFEXITED returned true.
    

    You're supposed to use the various macros listed there, such as WEXITSTATUS in your case, to make sense of wstatus. Other than using them, it's only safe to treat wstatus as an opaque blob (aside from a special case when it's 0).