Try::Tiny 和 $SIG{__DIE__} 在 Perl 中?

Try::Tiny and $SIG{__DIE__} in perl?

是否可以在具有 'overloaded' $SIG{__DIE__} 的 Perl 程序中使用 Try::Tiny? 例如,该程序的期望输出将是“捕获它”:

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Try::Tiny;

# here how to deal with try and catch 
$SIG{__DIE__} =
  sub { 
       print "died my way $_[0]"
};

my $rv;
try {die "its only a flesh wound"; }
catch { 
    $rv = undef; 
    print "caught it: $_ ";
};

感谢您的浏览和任何建议!

Try::Tiny 主要是 eval 调用的语法糖包装,eval 块内的 die 调用将调用 $SIG{__DIE__} 处理程序.作者 anticipated your objection,但最终决定坚持遗留行为。

Though it can be argued that $SIG{__DIE__} should be disabled inside of eval blocks, since it isn't people have grown to rely on it. Therefore in the interests of compatibility, try does not disable $SIG{__DIE__} for the scope of the error throwing code.

但您可以自行禁用它

try {
   local $SIG{__DIE__};
   ...
} catch { ... };

或重写 try .. catch 以执行您想要的操作。

sub my_try (&;@) {
    my ($try, @code_refs) = @_;
    local $SIG{__DIE__};
    Try::Tiny::try($try,@code_refs);
}

$SIG{__DIE__} 的文档显示 $^S 的使用是有原因的:您几乎总是想在 __DIE__ 处理程序中使用 $^S 以避免您提出的问题关于。

例如,

#!/usr/bin/perl
use strict;
use warnings;

use Try::Tiny;

$SIG{__DIE__} = sub {
   return if $^S;                      # If in eval.
   print(STDERR "Died: $_[0]");        # Send msg to STDERR, not STDOUT.
   exit( $! || ( $? >> 8 ) || 255 );   # Emulate die().
};

try {
   die("It's only a flesh wound.");
} catch {
   print("Caught: $_");
};

die("More than a flesh wound");

print("done.\n");

产出

Caught: It's only a flesh wound. at a.pl line 14.
Died: More than a flesh wound at a.pl line 19.