Day 14: What $! The $? (Proc::ChildError)

About the series: perlancar's 2014 Advent Calendar: Introduction to a selection of 24 modules which I published in 2014. Table of contents.

Finding out OS error message in Perl is pretty straightforward: just print out the $! variable. Example:

open my $fh, ">", "somefile" or die "Can't open file: $!";

The $! is pretty magical, it can return an integer (errno) or a string.

However, finding out child error message is not equally straightforward: there needs to be some bit-fiddling involved, which I always forget. To quote the perlvar manpage (or, perldoc -f system):

if ($? == -1) {
    print "failed to execute: $!\n";
elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
        ($? & 127),  ($? & 128) ? 'with' : 'without';
else {
    printf "child exited with value %d\n", $? >> 8;

I mean, are we really expected to do this incantation everytime we want to check the status ofsome command we launched using system()? So I wrote Proc::ChildError, which is just the above code packaged as a module. Thus you can say:

system "foo" or die explain_child_error();

As a bonus, the function accepts an option prog, for nicer error message (e.g. explain_child_error({prog=>'foo'}). So instead of:

failed to execute: permission denied
died with signal 15, without coredump
exited with code 100

You get:

foo failed to execute: permission denied
foo died with signal 15, without coredump
foo exited with code 100

Small stuffs, but it's just another cognitive load I can shave off.

Leave a comment

About perlancar

user-pic #perl #indonesia