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

Viewed 226

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.

2 Answers

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).

Related