I was doing an exercise for university where I had to return a value with exit, that value was actually a count of something. This could be above 255 (which exit() can't handle) but the teacher suggested to use test data where the count could never go above that value.
After all this, I needed to handle this count value, the exit status, I got this value in the main process by using waitpid(). To my surprise, if the child process returned 1, the "real" value in the main process was 256, 2 was 512 and so on...
I needed to print this value so I simply divided it by 256 and it was done. However, if I use the WEXITSTATUS() macro, I'll also get this value the way I want it...
I looked at C source code and this is what I found out:
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
I understand what's happening here, for instance, 512 in binary is 10 0000 0000, shifting 8 o the right will give 00 0000 0010, which is 2 in decimal. What I don't understand in this macro is that & operator and the fact that 0xff00 seems a random number (it probably isn't, where does it come from though?). What does this do exactly, why is there "& 0xff00" in the macro? Wouldn't it work with out it?
And the real question in this topic, is the same thing to call this macro in my code as dividing by 256?
And the real question in this topic, is the same thing to call this macro in my code as dividing by 256?
It will probably always work in the cases where the child process terminates normally (i.e., by calling exit(), not by a segmentation fault, assertion failure, etc.).
The status stored by waitpid()
encodes both the reason that the child process was terminated and the exit code. The reason is stored in the least-significant byte (obtained by status & 0xff
), and the exit code is stored in the next byte (masked by status & 0xff00
and extracted by WEXITSTATUS()
). When the process terminates normally, the reason is 0 and so WEXITSTATUS
is just equivalent to shifting by 8 (or dividing by 256). However, if the process is killed by a signal (such as SIGSEGV), there is no exit code, and you have to use WTERMSIG
to extract the signal number from the reason byte.