在 perl 中尝试::Tiny 和 $SIG{__DIE__}?

tur*_*tle 8 perl

是否可以在具有“重载”的 Perl 程序中使用 Try::Tiny $SIG{__DIE__}?例如,这个程序的期望输出是“caught it”:

#!/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: $_ ";
};
Run Code Online (Sandbox Code Playgroud)

感谢您的关注和任何建议!

ike*_*ami 7

使用$SIG{__DIE__}show的文档$^S是有原因的:您几乎总是希望$^S__DIE__处理程序中使用来避免您所询问的问题。

例如,

#!/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");
Run Code Online (Sandbox Code Playgroud)

产出

Caught: It's only a flesh wound. at a.pl line 14.
Died: More than a flesh wound at a.pl line 19.
Run Code Online (Sandbox Code Playgroud)


mob*_*mob 5

Try::Tiny主要是eval调用的语法糖包装器,块die内的eval调用将调用$SIG{__DIE__}处理程序。作者预料到您的反对,但最终决定坚持遗留行为。

尽管可以说$SIG{__DIE__}应该在eval块内禁用 它,因为人们还没有成长为依赖它。因此,在兼容性的利益,try不会禁用$SIG{__DIE__}的错误代码投掷的范围。

但是你可以自己禁用它

try {
   local $SIG{__DIE__};
   ...
} catch { ... };
Run Code Online (Sandbox Code Playgroud)

或重写try .. catch以做你想做的事。

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