Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   Shifting error codes (http://www.velocityreviews.com/forums/t911654-shifting-error-codes.html)

Marc Girod 10-25-2009 06:07 PM

Shifting error codes
 
Hi,

The code I maintain used to shift values meant as exit codes.

# Shift the status up so it looks like an exit status.
$rc = $2 << 8;

This practice seemed justified by the paragraph on $? in perlvar,
although, and this is my question, I am not sure how to read it
anymore.

I found that the return codes were not as expected:

$ perl -e 'exit 255'; echo $?
255
$ perl -e 'exit 256'; echo $?
0

So, should one ever shift codes leftwards,
or only rightwards codes received from sub-processes?

Thanks,
Marc

Jens Thoms Toerring 10-25-2009 09:33 PM

Re: Shifting error codes
 
Marc Girod <marc.girod@gmail.com> wrote:
> The code I maintain used to shift values meant as exit codes.


> # Shift the status up so it looks like an exit status.
> $rc = $2 << 8;


> This practice seemed justified by the paragraph on $? in perlvar,
> although, and this is my question, I am not sure how to read it
> anymore.


> I found that the return codes were not as expected:


> $ perl -e 'exit 255'; echo $?
> 255
> $ perl -e 'exit 256'; echo $?
> 0


Looks like you're on some kind of UNIX. And on UNIX the exit
value of a program is the lowest 8 bits of the return status
value only (i.e. a value between 0 and 255), higher bits being
used for information why the process stopped (e.g. normally by
calling exit() or because it was killed due to a signal etc.).
IIRC, higher order bits in the value passed to exit() simply
get masked out, so they don't make it through to '$?'.

> So, should one ever shift codes leftwards,


As long as you can guarantee that the result isn't larger
than 255 it's ok, otherwise things won't work as expected.

> or only rightwards codes received from sub-processes?


Sorry, but I don't understand what's meant by this.

Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de

Alan Curry 10-25-2009 10:15 PM

Re: Shifting error codes
 
In article <7kjuhtF3a3gtfU1@mid.uni-berlin.de>,
Jens Thoms Toerring <jt@toerring.de> wrote:
>Marc Girod <marc.girod@gmail.com> wrote:
>
>As long as you can guarantee that the result isn't larger
>than 255 it's ok, otherwise things won't work as expected.
>
>> or only rightwards codes received from sub-processes?

>
>Sorry, but I don't understand what's meant by this.


He means the return value from perl's system(). perlfunc says:

The return value is the exit status of the program as returned
by the "wait" call. To get the actual exit value, shift right
by eight (see below).

I assume that this evil magic number is a leftover from perl's early years
when there were no modules, and no easy way to make the system's WIFEXITED,
WEXITSTATUS, and related macros available inside a perl script. Does anybody
know what might happen if you compiled perl on a POSIX system that didn't use
the same bit layout for an exit status? Would it translate the status code,
possibly losing information along the way if some of the bitfields are
differently sized? Or does it just give you the raw number, and let you trip
over the bad advice in perlfunc? Either way, something is wrong here.

Better just treat the return value of system() as a boolean and check
${^CHILD_ERROR_NATIVE} if you need details. At least it has reasonable
documented behavior.

--
Alan Curry

Alan Curry 10-26-2009 01:17 AM

Re: Shifting error codes
 
In article <ho2fr6-kqd1.ln1@osiris.mauzo.dyndns.org>,
Ben Morrow <ben@morrow.me.uk> wrote:
>
>Quoth pacman@kosh.dhis.org (Alan Curry):
>>
>> I assume that this evil magic number is a leftover from perl's early years
>> when there were no modules, and no easy way to make the system's WIFEXITED,
>> WEXITSTATUS, and related macros available inside a perl script. Does anybody
>> know what might happen if you compiled perl on a POSIX system that didn't use
>> the same bit layout for an exit status? Would it translate the status code,
>> possibly losing information along the way if some of the bitfields are
>> differently sized? Or does it just give you the raw number, and let you trip
>> over the bad advice in perlfunc? Either way, something is wrong here.

>
>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/...s/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.

>
>> Better just treat the return value of system() as a boolean and check
>> ${^CHILD_ERROR_NATIVE} if you need details. At least it has reasonable
>> documented behavior.

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

--
Alan Curry

Alan Curry 10-26-2009 03:57 AM

Re: Shifting error codes
 
In article <iicfr6-v0f1.ln1@osiris.mauzo.dyndns.org>,
Ben Morrow <ben@morrow.me.uk> wrote:
>
>Quoth pacman@kosh.dhis.org (Alan Curry):
>> In article <ho2fr6-kqd1.ln1@osiris.mauzo.dyndns.org>,
>> Ben Morrow <ben@morrow.me.uk> wrote:
>> >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/...s/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.

>
>Unix is not POSIX, nor is it XPG (trademarks aside). There are a lot of


So what you meant by "Unix semantics" as applied to system()/wait() then is
in fact "bit-for-bit compatibility with V7"? I'm not sure that's a better
definition than what the IEEE/OpenGroup people have come up with.

[...]
>macro, which I suspect won't work at all. (It seems that the only
>systems Perl supports that *don't* use 'normal' exit statusseses are VMS
>and BeOS/Haiku.)


Rampant binary compatibility allows you to get away with hardcoded magic
numbers instead of using the proper abstractions. This is great if you're a
sloppy coder, not so much if you're trying to do the right thing.

--
Alan Curry


All times are GMT. The time now is 12:34 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.