Andrew Savige wrote:

BTW, this slip-up is also a good advertisement for ensuring that your
test suite tests all examples given in your documentation to ensure
that they actually work.



Hey, good point.  I'll start with that, then.

I'm familiar with the make-up of the 16-bit return value of the system call.
What I want to learn more about is the possibility that a process could
crash and yet return a 0 exit code. I had not thought that possible,
and hence, had seen no need to test for $? & 127.



I did a simple test on Linux.

This is file crash.c:
-------------------------------------------
#include <stdlib.h>
int main(int argc, char* argv[])
{
   return 5 / atoi(argv[1]);
}
-------------------------------------------

After compiling with:

cc crash.c

running this Perl program:

use strict;
sub div_by_zero { exec("./a.out $_[0]"); die "should not be here" }
defined(my $pid = fork()) or die "fork: $!";
if ($pid == 0) {
   warn "child, my pid $$\n";
   div_by_zero(0);      # sig 8
   # div_by_zero();     # sig 11
   exit;
}
warn "parent, my pid $$\n";
waitpid($pid, 0);
my $rv  = $? >> 8;
my $sig = $? & 127;
warn "$$: rv=$rv sig=$sig\n";

produces:

parent, my pid 12091
child, my pid 12092
12091: rv=0 sig=8

Replacing div_by_zero() above with:

sub div_by_zero { 5 / shift }

produced:

parent, my pid 12133
child, my pid 12134
Illegal division by zero at g2.pl line 2.
12133: rv=255 sig=0

Perl is catching this one it seems. However, using this one:

sub div_by_zero { warn "sleeping"; sleep(60) }

then manually killing the child process (with SIGTERM), produces:

parent, my pid 12356
child, my pid 12357
sleeping at g2.pl line 3.
12356: rv=0 sig=15

It's pretty rare and no biggie to me, but if I were implementing it
I would check the signal value in addition to the return value.



That's why I wanted to get this on CPAN. I knew others could point out things I'd never think of. ;)

I just checked my code.  Here's what it's doing right now:

           $child_registry{$child}[1] = $? >> 8;
           $successes++ if ( $? == 0 );

I'm only saving the 8-bit exit value for the user to inspect, BUT I'm only considering the execution successful if all 16 bits are off, so that means your crash example above would be marked as a failure, even though the exit value is 0.

It seems like categorizing non-zero $? values as failures is still a good idea, but since it is possible that a block could fail and still return 0, that will confuse users inspecting the return value trying to figure out what went wrong. The obvious solution is give the user all 16 bits, instead of $? >> 8 for them.

Which sucks, cause no one likes doing the $? >> 8 part. It's ugly. I was hoping to Keep It Simple by doing it for them.

-ofer



Reply via email to