0

When I run the following code (headers and main entry ommitted)

void fork11()
{
    pid_t pid[N];
    int i;
    int child_status;

    for (i = 0; i < N; i++)
    if ((pid[i] = fork()) == 0)
        exit(100+i); /* Child */
    for (i = N-1; i >= 0; i--) {
        pid_t wpid = waitpid(pid[i], &child_status, 0);
        if (WIFEXITED(child_status)) {
            printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status));
            printf("child_status: %d\n", child_status);
        } else {            
            printf("Child %d terminate abnormally\n", wpid);
        }    
    }
}

the result is

Child 5126 terminated with exit status 104
child_status: 26624
Child 5125 terminated with exit status 103
child_status: 26368
Child 5124 terminated with exit status 102
child_status: 26112
Child 5123 terminated with exit status 101
child_status: 25856
Child 5122 terminated with exit status 100
child_status: 25600

with some digging around I find WEXITSTATUS is a simple macro

#define WEXITSTATUS(x) ((_W_INT(x) >> 8) & 0x000000ff)

take child process 5126 for example, waitpid converts 104 to 26624=0x6800, WEXITSTATUS converts 26624 back to 104=0x68, I tried to look up source code of waitpid but ended up with some kernel functions which I can't understand... could anyone explain a little bit about how does waitpid convert exit code? It seems fairly simple in the above example but I think it's much more than that, thanks!

mzoz
  • 1,273
  • 1
  • 14
  • 28
  • 1
    I have a somehow similar question about an exit status, [How to detect if shell failed to execute a command after popen call? Not to confuse with the command exit status](https://stackoverflow.com/a/60013200/8339821). My understanding is that process mail fail, process may be signaled, and shell may fail. Hope you will find some useful information in the answer I've linked. – user14063792468 Feb 27 '20 at 13:26
  • @ЯрославМашко thanks mate it's very helpful, I still wonder what else is going on besides shifting bits around... – mzoz Feb 27 '20 at 13:34
  • If you're using glibc, you'll want to look at https://code.woboq.org/gcc/include/bits/waitstatus.h.html – Shawn Feb 27 '20 at 14:36
  • @ЯрославМашко thank you mate, i was looking for that answer too. Have a nice day. – Türker Berke Yıldırım Feb 27 '20 at 14:37
  • shift and mask... what else can? or you talking about some other process activity? – user14063792468 Feb 27 '20 at 15:01

1 Answers1

0

When a process exits, the return value passed to the exit() function is used as a parameter for the actual int (4 bytes) passed to any process that waits for it. In addition to the 8 bits of this status code, more information is being passed.

For example, in the actual (final) exit code (the entire 4 bytes), it's being specified whether the process was signaled or not.

As seen here about WEXITSTATUS:

This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3)...

This means that processes cannot exit with codes that require more than 8 bits.

Raz Rotenberg
  • 599
  • 4
  • 9