I need to eval
some code in Perl that might some times contain an exit()
call in it. A very simplified example of this would be:
use strict;
use warnings;
eval "some_function()";
die $@ if $@;
print "Still alive!\n";
sub some_function {
print "Hello from some_function\n";
exit;
}
I never get to "Still alive!" because of the exit()
call.
I tried setting some keys in %SIG
(QUIT, STOP, TERM, BREAK, etc) but that didn't work. I also attempted to redefine CORE::exit
with no success.
How can I prevent an exit()
call from being effective when being eval
ed?
You can override exit
, but you must do so at compile-time. So use a flag to signal whether the override is active or not.
our $override_exit = 0;
BEGIN {
*CORE::GLOBAL::exit = sub(;$) {
CORE::exit( $_[0] // 0 ) if !$override_exit;
die "EXIT_OVERRIDE\n";
};
}
eval {
local $override_exit = 1;
some_function();
};
if ( !$@ ) {
say "Normal return";
} elsif ( $@ eq "EXIT_OVERRIDE\n" ) {
say "Exit called";
} else {
print "Exception: $@";
}
But that creates an exception that might be caught unintentionally. So let's use last
instead.
our $override_exit = 0;
BEGIN {
*CORE::GLOBAL::exit = sub(;$) {
CORE::exit( $_[0] // 0 ) if !$override_exit;
no warnings qw( exiting );
last EXIT_OVERRIDE;
};
}
my $exit_called = 1;
EXIT_OVERRIDE: {
local $override_exit = 1;
eval { some_function() };
$exit_called = 0;
}
if ( $exit_called ) {
say "Exit called";
} elsif ( $@ ) {
print "Exception: $@";
} else {
say "Normal return";
}
Note that eval BLOCK
is used to catch exceptions. eval EXPR
is used to compile code.