[英]How to override exit() call in Perl eval block
I need to eval
some code in Perl that might some times contain an exit()
call in it.我需要在 Perl 中
eval
一些代码,这些代码有时可能包含exit()
调用。 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.因为
exit()
调用。
I tried setting some keys in %SIG
(QUIT, STOP, TERM, BREAK, etc) but that didn't work.我尝试在
%SIG
设置一些键(QUIT、STOP、TERM、BREAK 等),但是没有用。 I also attempted to redefine CORE::exit
with no success.我还尝试重新定义
CORE::exit
,但没有成功。
How can I prevent an exit()
call from being effective when being eval
ed?在
eval
ed 时如何防止exit()
调用生效?
You can override exit
, but you must do so at compile-time.您可以覆盖
exit
,但您必须在编译时这样做。 So use a flag to signal whether the override is active or not.因此,使用标志来表示覆盖是否处于活动状态。
our $override_exit = 0;
BEGIN {
*CORE::GLOBAL::exit = sub(;$) {
die "EXIT_OVERRIDE\n" if $override_exit;
CORE::exit($_[0] // 0);
};
}
eval {
local $override_exit = 1;
some_function();
};
my $exit_was_called = $@ eq "EXIT_OVERRIDE\n";
die $@ if $@ && !$exit_was_called;
die("Exit called\n") if $exit_was_called;
But that creates an exception that might be caught unintentionally.但这会创建一个可能无意中捕获的异常。 So let's use
last
instead.所以让我们用
last
代替。
our $override_exit = 0;
BEGIN {
*CORE::GLOBAL::exit = sub(;$) {
no warnings qw( exiting );
last EXIT_OVERRIDE if $override_exit;
CORE::exit($_[0] // 0);
};
}
my $exit_was_called = 1;
EXIT_OVERRIDE: {
local $override_exit = 1;
eval { some_function() };
die $@ if $@;
$exit_was_called = 0;
}
die("Exit called\n") if $exit_was_called;
Note that eval BLOCK
is used to catch exception.请注意,
eval BLOCK
用于捕获异常。 eval EXPR
is used to compile code. eval EXPR
用于编译代码。
exit
isn't meant to be trapped, so eval
isn't the solution here. exit
并不意味着被困,所以eval
不是这里的解决方案。 You could put the remaining code you need to run in an END
block:您可以将运行所需的剩余代码放在
END
块中:
some_function();
END { print "Still alive! For now...\n"; }
sub some_function {
print "Hello from some_function\n";
exit;
}
But if you absolutely, positively need to prevent exit
from killing the script, you'll have to redefine exit()
at compile time:但是,如果您绝对需要防止
exit
杀死脚本,则必须在编译时重新定义exit()
:
BEGIN { *CORE::GLOBAL::exit = sub (;$) { } } # Make exit() do nothing
some_function();
print "Still alive!\n"; # Gets printed
*CORE::GLOBAL::exit = *CORE::exit; # Restore exit()
exit;
print "I'm dead here.\n"; # Doesn't get printed
sub some_function { exit }
The Test::Trap module from the CPAN can be used to encapsulate this bit of ugliness for you, if you're interested in a more robust solution.如果您对更健壮的解决方案感兴趣,可以使用 CPAN 中的 Test::Trap 模块为您封装这种丑陋之处。 Personally I would locally patch the
exit
ing some_function()
to use croak
instead, and maybe file a bug report with the patch if it's a module.就我个人而言,我会在本地修补
some_function()
的exit
以使用croak
,并且如果它是一个模块,可能会随补丁一起提交错误报告。
If you're just eval
ing user input and you don't want them to be able to call exit
, verify that the string contains no calls to exit
or to a subroutine that would indirectly exit, then eval
it.如果您只是
eval
用户输入并且您不希望他们能够调用exit
,请验证该字符串不包含对exit
或间接退出的子例程的调用,然后对其进行eval
。 Personally I'd be more afraid of unlink
and fork
than exit
if the user is inputting arbitrary code to be evaluated.就个人而言,如果用户输入要评估的任意代码,我会更害怕
unlink
和fork
不是exit
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.