New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
eval: DESTROY may overwrite $@ - exceptions are not handled #5965
Comments
From burkhard.meier@gmx.deCreated by burkhard.e.f.meier@t-online.deThis is a bug report for perl from burkhard.e.f.meier@t-online.de, ----------------------------------------------------------------- eval { package SomeClass; sub new sub DESTROY ......results in the output: G:\tmp>perl -w eval.pl It seems that "die" first sets $@, then the local objects' destructors are Perl Info
|
From @eserteBurkhard Meier (via RT) <perlbug@perl.org> writes:
I think the DESTROY method is responsible for preserving the value of Regards, -- Berlin Perl Mongers - http://berliner.pm.org |
From burkhard.meier@gmx.de
Come on, that's just a workaround... And who knows about this? BTW, does anybody if this specific problem will also occur in Perl6? Regards, |
From alex@chmrr.netHeya, -- |
From alex@chmrr.netperl-destroy.patchdiff -ru perl-current/pp_ctl.c perl-patched/pp_ctl.c
--- perl-current/pp_ctl.c 2005-07-08 13:03:02.000000000 -0400
+++ perl-patched/pp_ctl.c 2005-07-08 15:39:59.000000000 -0400
@@ -1432,6 +1432,7 @@
else {
sv_setpvn(ERRSV, message, msglen);
}
+ message = SvPV_const(ERRSV, msglen);
}
while ((cxix = dopoptoeval(cxstack_ix)) < 0
@@ -1471,6 +1472,12 @@
* minimal fix --GSAR */
PL_curcop = cx->blk_oldcop;
+ /* Leaving the block could run DESTROY blocks which might
+ * have altered $@; reset it here just in case */
+ if (message) {
+ sv_setpvn(ERRSV, message, msglen);
+ }
+
if (optype == OP_REQUIRE) {
const char* msg = SvPVx_nolen_const(ERRSV);
SV * const nsv = cx->blk_eval.old_namesv;
diff -ru perl-current/t/op/die.t perl-patched/t/op/die.t
--- perl-current/t/op/die.t 2005-07-06 16:38:38.000000000 -0400
+++ perl-patched/t/op/die.t 2005-07-08 15:42:12.000000000 -0400
@@ -1,6 +1,6 @@
#!./perl
-print "1..15\n";
+print "1..16\n";
$SIG{__DIE__} = sub { print ref($_[0]) ? ("ok ",$_[0]->[0]++,"\n") : @_ } ;
@@ -72,3 +72,27 @@
print "not " unless $ok;
print "ok 15\n";
}
+
+# [perl #17650] DESTROY can unset $@
+{
+ package SomeClass;
+
+ sub new {
+ my $self = {};
+ bless $self;
+ }
+
+ sub DESTROY {
+ eval { 1; };
+ }
+}
+
+{
+ local $SIG{__DIE__};
+ eval {
+ my $x = new SomeClass;
+ die;
+ };
+ print($@ ? "ok 16\n" : "not ok 16\n");
+}
+
|
From @iabynOn Fri, Jul 08, 2005 at 03:59:34PM -0400, Alex Vandiver wrote:
I don't think this fix is robust. You save the current PV value of ERRSV, -- |
From alex@chmrr.netOn Sun, 2005-07-10 at 14:29 +0100, Dave Mitchell wrote:
-- |
From alex@chmrr.netperl-destroy.patchdiff -ru perl-current/sv.c perl-patched/sv.c
--- perl-current/sv.c 2005-07-08 13:03:02.000000000 -0400
+++ perl-patched/sv.c 2005-07-18 00:12:01.000000000 -0400
@@ -5519,6 +5519,10 @@
PUSHMARK(SP);
PUSHs(tmpref);
PUTBACK;
+
+ /* Localise $@ so DESTROY caused by die can't reset $@ */
+ save_item(ERRSV);
+
call_sv((SV*)destructor, G_DISCARD|G_EVAL|G_KEEPERR|G_VOID);
diff -ru perl-current/t/op/die.t perl-patched/t/op/die.t
--- perl-current/t/op/die.t 2005-07-06 16:38:38.000000000 -0400
+++ perl-patched/t/op/die.t 2005-07-16 02:25:44.000000000 -0400
@@ -1,6 +1,6 @@
#!./perl
-print "1..15\n";
+print "1..17\n";
$SIG{__DIE__} = sub { print ref($_[0]) ? ("ok ",$_[0]->[0]++,"\n") : @_ } ;
@@ -72,3 +72,43 @@
print "not " unless $ok;
print "ok 15\n";
}
+
+# [perl #17650] DESTROY can unset $@
+{
+ package SomeClass;
+ sub new { return bless {}; }
+ sub DESTROY {
+ eval { 1; };
+ }
+}
+
+{
+ package SomeOtherClass;
+ sub new { return bless {}; }
+ sub DESTROY {
+ eval { die bless {}, "Moose"; }
+ }
+}
+
+{
+ local $SIG{__DIE__};
+ eval {
+ my $x = new SomeClass;
+ die;
+ };
+ print($@ ? "ok 16\n" : "not ok 16\n");
+
+ eval {
+ my $x = new SomeOtherClass;
+ die bless {}, "Thingy";
+ };
+ print($@ ? "ok 17\n" : "not ok 17\n");
+ print(ref $@ eq "Thingy" ? "ok 18\n" : "not ok 18\n");
+
+ eval {
+ my $s = new SomeOtherClass;
+ };
+ print($@ ? "not ok 19\n" : "ok 19\n");
+}
+
+
|
From @iabynOn Mon, Jul 18, 2005 at 01:14:43AM -0400, Alex Vandiver wrote:
I like the idea of localising $@ before calling DESTROY, but unfortunately lib/warnings..............................PROG: The behaviour being tested here is that a die in a DESTROY gets converted I'm not really sure offhand of the best way round this. Perhaps have an -- |
From @nwc10On Tue, Jul 19, 2005 at 01:19:19AM +0100, Dave Mitchell wrote:
Which means that it wasn't tested before being sent to the list. make test exists for a reason. Nicholas Clark |
From guest@guest.guest.xxxxxxxx
There's another problem with this work-around -- it breaks in the other tin-foil:/tmp glasser$ cat /tmp/localdie sub i_localize_dollar_at { # This could certainly be DESTROY eval { i_localize_dollar_at() }; my if ($error) { That is, localizing $@ in DESTROY solves the problem of "an eval inside I'm not sure if Alex's patch has this issue too. --dave |
From @smpeters
This bug has been resolved by documenting this behavior with a patch in |
@smpeters - Status changed from 'open' to 'resolved' |
Migrated from rt.perl.org#17650 (status was 'resolved')
Searchable as RT17650$
The text was updated successfully, but these errors were encountered: