在Test :: More中在eval期间保护全局变量

时间:2014-01-07 21:04:41

标签: perl error-handling eval test-more

我正在浏览Test :: More的代码,因为我想看看use_okrequire_ok是如何实现的(以及为什么Ovid不喜欢它们)。我来到了_eval子程序,其中包含一些我在eval调用期间保护变量时并不完全理解的特殊逻辑。我从Try::Tiny的文档中了解到处理$@是多么困难。但是,我不理解$!$SIG{__DIE__}的处理方式(下面的块被逐字复制):

# Work around oddities surrounding resetting of $@ by immediately
# storing it.
my( $sigdie, $eval_result, $eval_error );
{
    local( $@, $!, $SIG{__DIE__} );    # isolate eval
    $eval_result = eval $code;              ## no critic (BuiltinFunctions::ProhibitStringyEval)
    $eval_error  = $@;
    $sigdie      = $SIG{__DIE__} || undef;
}
# make sure that $code got a chance to set $SIG{__DIE__}
$SIG{__DIE__} = $sigdie if defined $sigdie;

$SIG{__DIE__}的处理与RT #34065有关,但我仍然没有得到它。为什么有必要在最后一行再次设置变量,因为它总是应该在块的最后一行设置?如果这些行的重点是将变量设置为eval调用中的变量,为什么必须首先将其本地化?

此外,如果使用eval而不使用错误变量错误变量意味着本地化$@$!,我们是否还必须本地化$?

1 个答案:

答案 0 :(得分:2)

我认为$sigdie可以明确地允许eval'd代码 set $SIG{__DIE__},同时不允许任何外部设置的处理程序在EVAL。

因此本地化会抑制外部值,但需要在块结束之前保存任何设置值,并在块之后将其设置为现在未本地化的版本。

我认为$!已本地化,但不是$?$^E等,原因是实际原因(也就是说,我猜人们会抱怨$!更改,但是不是别的什么。)