$ret = sub {
my @args = @_; # lexical to close over
my $sub_with_args = sub { $sub->(@args) };
- return Opcode::_safe_call_sv($root, $obj->{Mask}, $sub_with_args)
+
+ my @subret;
+ my $error;
+ do {
+ local $@; # needed due to perl_call_sv(sv, G_EVAL|G_KEEPERR)
+ @subret = (wantarray)
+ ? Opcode::_safe_call_sv($root, $obj->{Mask}, $sub_with_args)
+ : scalar Opcode::_safe_call_sv($root, $obj->{Mask}, $sub_with_args);
+ $error = $@;
+ };
+ if ($error) { # rethrow exception
+ $error =~ s/\t\(in cleanup\) //; # prefix added by G_KEEPERR
+ die $error;
+ }
+ return (wantarray) ? @subret : $subret[0];
};
}
}
}
use Safe 1.00;
-use Test::More tests => 6;
+use Test::More tests => 9;
my $safe = Safe->new('PLPerl');
$safe->permit_only(qw(:default sort));
my ($l_sorted, $p_sorted) = $func->(1,2,3);
is $l_sorted, "1,2,3";
is $p_sorted, "1,2,3";
+
+# check other aspects of closures created inside Safe
+
+my $die_func = $safe->reval(q{ sub { die @_ if @_; 1 } });
+
+# check $@ not affected by successful call
+$@ = 42;
+$die_func->();
+is $@, 42, 'successful closure call should not alter $@';
+
+ok !eval { $die_func->("died\n"); 1 }, 'should die';
+is $@, "died\n", '$@ should be set correctly';
+