gpt4 book ai didi

perl - 我如何编写一个不在 eval block 中触发的 SIG{__DIE__} 处理程序?

转载 作者:行者123 更新时间:2023-12-04 02:28:19 24 4
gpt4 key购买 nike

根据perldoc -f die ,其中记录了 $SIG{__DIE__}

Although this feature was to be run only right before your program was to exit, this is not currently so: the $SIG{__DIE__} hook is currently called even inside evaled blocks/strings! If one wants the hook to do nothing in such situations, put die @_ if $^S; as the first line of the handler (see $^S in perlvar). Because this promotes strange action at a distance, this counterintuitive behavior may be fixed in a future release.

所以让我们采用一个基本的信号处理程序,它将通过 eval { die 42 } 触发,

package Stupid::Insanity {
BEGIN { $SIG{__DIE__} = sub { print STDERR "ERROR"; exit; }; }
}

我们用

确保安全
package Stupid::Insanity {
BEGIN { $SIG{__DIE__} = sub { return if $^S; print STDERR "ERROR"; exit; }; }
}

现在这将不会通过 eval { die 42 } 触发,但是当相同的代码在 BEGIN {} 中时它会触发 block 喜欢

BEGIN { eval { die 42 } }

这可能看起来晦涩难懂,但它是真实世界,因为您可以看到它是 used in this method here (where the require fails and it's caught by an eval) ,或者就我而言,这里特别是 Net::DNS::Parameters .你可能认为你也可以捕获编译器阶段,就像这样,

BEGIN {
$SIG{__DIE__} = sub {
return if ${^GLOBAL_PHASE} eq 'START' || $^S;
print STDERR "ERROR";
exit;
};
}

这将适用于上述情况,但遗憾的是,它不适用于需要包含 BEGIN 语句的文档,

eval "BEGIN { eval { die 42 } }";

有没有办法解决这个问题并编写一个不干扰 eval$SIG{__DIE__} 处理程序?

最佳答案

检查caller(1)

就在兔子洞的更深处,[caller(1)]->[3] eq '(eval)'

return if [caller(1)]->[3] eq '(eval)' || ${^GLOBAL_PHASE} eq 'START' || $^S;

抓取整个调用堆栈

您可以抓取整个堆栈并确保您没有深入评估,

for ( my $i = 0; my @frame = caller($i); $i++ ) {
return if $frame[3] eq '(eval)'
}

是的,这完全是精神错乱。感谢 mst 在 irc.freenode.net/#perl 上的指点。

关于perl - 我如何编写一个不在 eval block 中触发的 SIG{__DIE__} 处理程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65835906/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com