Quoth (e-mail address removed) (Alan Curry):
Check the source
. This has changed over the years, largely as a
result of pressure from the VMS people (VMS has W*, but doesn't use exit
codes looking anything like the POSIX ones). It turned out to be easier
to fix perl than to fix all the scripts assuming Unix semantics for $?.
Unix semantics? The Unix definition is here:
http://www.opengroup.org/onlinepubs/9699919799/functions/waitpid.html
And that definition doesn't mandate any particular arrangement of bits. Unix
requires the use of W*() macros to examine an exit code, unless you're just
comparing it to 0 which is a special value.
"Shift by 8" is unwarranted chumminess with the implementation, as wrong as
hardcoding an assumption that EAGAIN==11, or O_NONBLOCK==0x800, or LOCK_EX==2
which used to also be encouraged by perlfunc, and is still sort of implied
to be correct there. (I wonder if that's subject to translation too)
Current behaviour is to extract the relevant bits using the proper W*
macros and then build up a fake $? value that looks the way you would
expect. ${^C_E_N} is there in case you need the *actual* return value.
I see now that this is better documented in the perlvar entry for $?.
Before, I was looking at the perlfunc entry for system(). I don't see
anything that explicitly says the value returned by system is the same value
that gets put into $?. They're both described in similar terms, and they're
obviously strongly related, but since at least one of them is being mangled
from native format to "shift by 8" format, the situation is still not clear.
It's documented that ($? >> 8) will be the lowest 8 bits of the process'
exit value. The signal and core stuff is non-portable, but then that's
to be expected. (It will be correct if the OS provides reasonable
definitions of the WTERMSIG and WCOREDUMP macros.)
So the you can litter your code with magic numebrs that match the magic
numbers that perl puts into $? or you can write something readable instead,
and as a bonus get the un-truncated exit value, by using
${^CHILD_ERROR_NATIVE} and the POSIX module.
But wait... according to the POSIX module's man page:
WEXITSTATUS WEXITSTATUS($?) returns the normal exit status
of the child process (only meaningful if
WIFEXITED($?) is true)
I hope that's a documentation bug. I hope it should really be
WEXITSTATUS(${^CHILD_ERROR_NATIVE}). Or does the POSIX module's WEXITSTATUS()
not actually do the same thing as the C-level WEXITSTATUS(), does it actually
expect the perl-mangled $? variable instead of the real status code? If that
documentation is correct, then I can see no way at all to portably get a
child process's full exit status in perl. What a clusterfsck.