Why is it that when I shift the exit code, $?, in Perl by eight, I get 255 when I expect it to be -1?
The exit status returned by 'wait()' is a 16-bit value. Of those 16 bits, the high-order 8 bits come from the low-order 8 bits of the value returned by 'exit()' — or the value returned from main()
. If the program dies naturally, the low-order 8 bits of the 16 are all zero. If the program dies because of signal, the low-order 8 bits encode the signal number and a bit indicating whether a core dump happened. With a signal, the exit status is treated as zero — programs like the shell tend to interpret the low-order bits non-zero as a failure.
15 8 7 0 Bit Position
+-----------------+
| exit | signal |
+-----------------+
Most machines actually store the 16-bit value in a 32-bit integer, and that is handled with unsigned arithmetic. The higher-order 8 bits of the 16 may be all 1 if the process exited with 'exit(-1)', but that will appear as 255 when shifted right by 8 bits.
If you really want to convert the value to a signed quantity, you would have to do some bit-twiddling based on the 16th bit.
$status >>= 8;
($status & 0x80) ? -(0x100 - ($status & 0xFF)) : $status;
See also SO 774048 and SO 179565.
Perl returns a subprocess exit code in the same manner as the C runtime library macro WEXITSTATUS
, which has the following description in wait(2)
:
WEXITSTATUS(status) evaluates to the least significant eight bits of the return code of the child which terminated, which may have been set as the argument to a call to exit() or as the argument for a return statement in the main program. This macro can only be evaluated if WIFEXITED returned non-zero.
The important part here is the least significant eight bits. This is why you are getting an exit code of 255. The perlvar
man page describes $?
as follows:
$? The status returned by the last pipe close, backtick (‘‘) com- mand, successful call to wait() or waitpid(), or from the sys- tem() operator. This is just the 16-bit status word returned by the wait() system call (or else is made up to look like it). Thus, the exit value of the subprocess is really ("$? >> 8"), and "$? & 127" gives which signal, if any, the process died from, and "$? & 128" reports whether there was a core dump.
There is no special handling here for negative numbers in the exit code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With