diff options
author | Zefram <zefram@fysh.org> | 2010-04-20 21:32:53 +0100 |
---|---|---|
committer | Zefram <zefram@fysh.org> | 2010-04-21 00:06:13 +0100 |
commit | 96d9b9cd40f1d98fda790eb12b5cdbeef8b48a81 (patch) | |
tree | 831956f1da7b8d410d9f54fb160c5f6c9eaa4f53 /t | |
parent | 157ebcf587b4b84c105e6157097a480172b5079d (diff) | |
download | perl-96d9b9cd40f1d98fda790eb12b5cdbeef8b48a81.tar.gz |
make die reliably hand error to post-eval code
Put the exception into $@ last thing before longjmping to the op following
the eval block, where previously it went into $@ before unwinding the
stack. This change means that the exception is not liable to be lost
by $@ being clobbered by destructors, cleanup code, or restoration after
"local $@". The code running immediately after eval can now rely on $@
accurately indicating the exception status of the eval.
Diffstat (limited to 't')
-rw-r--r-- | t/op/die_except.t | 81 | ||||
-rw-r--r-- | t/op/eval.t | 2 |
2 files changed, 83 insertions, 0 deletions
diff --git a/t/op/die_except.t b/t/op/die_except.t new file mode 100644 index 0000000000..b0fcadb8c8 --- /dev/null +++ b/t/op/die_except.t @@ -0,0 +1,81 @@ +#!./perl + +print "1..12\n"; +my $test_num = 0; +sub ok { + print $_[0] ? "" : "not ", "ok ", ++$test_num, "\n"; +} + +{ + package End; + sub DESTROY { $_[0]->() } + sub main::end(&) { + my($cleanup) = @_; + return bless(sub { $cleanup->() }, "End"); + } +} + +my($val, $err); + +$@ = "t0\n"; +$val = eval { + $@ = "t1\n"; + 1; +}; $err = $@; +ok $val == 1; +ok $err eq ""; + +$@ = "t0\n"; +$val = eval { + $@ = "t1\n"; + do { + die "t3\n"; + }; + 1; +}; $err = $@; +ok !defined($val); +ok $err eq "t3\n"; + +$@ = "t0\n"; +$val = eval { + $@ = "t1\n"; + local $@ = "t2\n"; + 1; +}; $err = $@; +ok $val == 1; +ok $err eq ""; + +$@ = "t0\n"; +$val = eval { + $@ = "t1\n"; + local $@ = "t2\n"; + do { + die "t3\n"; + }; + 1; +}; $err = $@; +ok !defined($val); +ok $err eq "t3\n"; + +$@ = "t0\n"; +$val = eval { + $@ = "t1\n"; + my $c = end { $@ = "t2\n"; }; + 1; +}; $err = $@; +ok $val == 1; +ok $err eq ""; + +$@ = "t0\n"; +$val = eval { + $@ = "t1\n"; + my $c = end { $@ = "t2\n"; }; + do { + die "t3\n"; + }; + 1; +}; $err = $@; +ok !defined($val); +ok $err eq "t3\n"; + +1; diff --git a/t/op/eval.t b/t/op/eval.t index 98fbc1e51c..ff5004eae5 100644 --- a/t/op/eval.t +++ b/t/op/eval.t @@ -526,6 +526,8 @@ if (eval "use Devel::Peek; 1;") { my $in = <IN>; my ($first, $second) = split (/\*\*\*\*\*\*\n/, $in, 2); $first =~ s/,pNOK//; + s/ PV = 0x[0-9a-f]+/ PV = 0x/ foreach $first, $second; + s/ LEN = [0-9]+/ LEN = / foreach $first, $second; $ok = 1 if ($first eq $second); } } |