Skip to main content

DESTROY your exit()

Recently we’ve been facing an interesting problem. Even if we used ‘die()’, the exit code of the script remained 0, that is, “success”. Several hours of careful debugging of our script and nothing special was discovered.

The next day started with tries to reproduce that and in the end we had this:

package Bug::Destroy::System;
sub new {
    my $pkg = shift;
    bless {}, $pkg;
}

sub DESTROY {
    # we need to call some system routine
    system("echo hello");
}

package main;
my $t = Bug::Destroy::System->new();
die "Oh, no, bad thing happened!";

You can try it on your system, it will exit with 0 provided that your system has the “echo” command.

The whole thing happens because of global $? variable which gets modified by system(), so first you have die() that sets $? to 1, then the destructors start to be executed, one of them calls system() that modifies $? to 0 as echo has succeeded. Then the script exits with whatever is in $?, i.e. 0. Pretty straightforward, you know?

In order to minimize the consequences, always do local() on your $? in DESTROY block. You’ll save a lot of time.