如何在Perl eval块中重写exit()调用
我需要如何在Perl eval块中重写exit()调用,perl,eval,Perl,Eval,我需要eval一些Perl代码,这些代码有时可能包含exit()调用。一个非常简单的例子是: use strict; use warnings; eval "some_function()"; die $@ if $@; print "Still alive!\n"; sub some_function { print "Hello from some_function\n"; exit; } 因为调用了exit(),所以我从来没有听到过“还活着!” 我尝试在%SIG
eval
一些Perl代码,这些代码有时可能包含exit()
调用。一个非常简单的例子是:
use strict;
use warnings;
eval "some_function()";
die $@ if $@;
print "Still alive!\n";
sub some_function {
print "Hello from some_function\n";
exit;
}
因为调用了exit()
,所以我从来没有听到过“还活着!”
我尝试在%SIG
中设置一些键(退出、停止、终止、中断等),但没有成功。我还试图重新定义CORE::exit
,但没有成功
如何防止
exit()
调用在执行eval
ed时生效?exit
并不意味着被捕获,因此eval
不是解决方案。您可以将需要运行的剩余代码放在END
块中:
some_function();
END { print "Still alive! For now...\n"; }
sub some_function {
print "Hello from some_function\n";
exit;
}
但是,如果您确实需要防止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 }
如果您对更健壮的解决方案感兴趣,可以使用CPAN中的Test::Trap模块来封装这一点。就我个人而言,我会在本地修补exit
ingsome_function()
以使用croak
,如果它是一个模块,我可能会用修补程序提交错误报告
如果您只是
eval
ing用户输入,并且您不希望他们能够调用exit
,请验证该字符串不包含对exit
或将间接退出的子例程的调用,然后eval
it。就我个人而言,如果用户输入任意代码进行评估,我更担心取消链接
和分叉
,而不是退出
。您可以覆盖退出
,但必须在编译时这样做。因此,使用一个标志来表示超越是否处于活动状态
我们的$override\u exit=0;
开始{
*核心::全局::退出=子(;$){
如果$OVERRIDE\u EXIT,则禁用“EXIT\u OVERRIDE\n”;
CORE::exit($\u0]//0);
};
}
评估{
本地$override_exit=1;
一些函数();
};
我的$exit\u被调用=$@eq“exit\u覆盖\n”;
死$@如果$@&$出口被称为出口;
如果调用了$Exit\u,则为die(“调用Exit\n”);
但这会创建一个可能被无意中捕获的异常。因此,让我们使用last
我们的$override\u exit=0;
开始{
*核心::全局::退出=子(;$){
无警告qw(退出);
如果$OVERRIDE\u EXIT,则上次退出\u OVERRIDE;
CORE::exit($\u0]//0);
};
}
我的$exit_被称为=1;
退出超控:{
本地$override_exit=1;
eval{some_function()};
死亡$@如果$@;
$exit_被调用=0;
}
如果调用了$Exit\u,则为die(“调用Exit\n”);
请注意,
eval块
用于捕获异常<代码>eval EXPR用于编译代码。非常好,再次感谢。:-)因此,如果evaled代码显式调用CORE::exit
,我想我将无法阻止它。对吗?我想,您必须安装一个操作码检查器来更改exit
操作码的ppaddr。