From: Vincent Pit Date: Thu, 26 Mar 2009 19:07:59 +0000 (+0100) Subject: Properly unmortalize the wizard after removing it from the global hash X-Git-Tag: v0.34~6 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FVariable-Magic.git;a=commitdiff_plain;h=ff3e3f39b252f61a6061d3e3de3f24147bbdd77d Properly unmortalize the wizard after removing it from the global hash --- diff --git a/MANIFEST b/MANIFEST index d64a464..dadd63a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -42,6 +42,7 @@ t/91-pod.t t/92-pod-coverage.t t/95-portability-files.t t/99-kwalitee.t +t/lib/Variable/Magic/TestDestroyRequired.pm t/lib/Variable/Magic/TestDieRequired.pm t/lib/Variable/Magic/TestValue.pm t/lib/Variable/Magic/TestWatcher.pm diff --git a/Magic.xs b/Magic.xs index 0bd0bfd..f9587ab 100644 --- a/Magic.xs +++ b/Magic.xs @@ -1028,8 +1028,17 @@ STATIC int vmg_wizard_free(pTHX_ SV *wiz, MAGIC *mg) { if (hv_delete(MY_CXT.wizards, buf, sprintf(buf, "%u", w->sig), 0) != wiz) return 0; } - SvFLAGS(wiz) |= SVf_BREAK; - FREETMPS; + + /* Unmortalize the wizard to avoid it being freed in weird places. */ + if (SvTEMP(wiz) && !SvREFCNT(wiz)) { + const I32 myfloor = PL_tmps_floor; + I32 i; + for (i = PL_tmps_ix; i > myfloor; --i) { + SV * const sv = PL_tmps_stack[i]; + if (sv && sv == wiz) + PL_tmps_stack[i] = NULL; + } + } if (w->cb_data) SvREFCNT_dec(SvRV(w->cb_data)); if (w->cb_get) SvREFCNT_dec(SvRV(w->cb_get)); diff --git a/t/15-self.t b/t/15-self.t index 700cb17..504c4b2 100644 --- a/t/15-self.t +++ b/t/15-self.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 16; +use Test::More tests => 17; use Variable::Magic qw/wizard cast dispell getdata getsig/; @@ -50,9 +50,13 @@ my $c = 0; ok($res, 're-re-cast on self is valid'); } +eval q[ + use lib 't/lib'; + BEGIN { require Variable::Magic::TestDestroyRequired; } +]; +is $@, '', 'wizard destruction at the end of BEGIN-time require doesn\'t panic'; + if ((defined $ENV{PERL_DESTRUCT_LEVEL} and $ENV{PERL_DESTRUCT_LEVEL} >= 3) or eval "use Perl::Destruct::Level level => 3; 1") { diag 'Test global destruction'; } - -# is($c, 0, 'magic destructor is called'); diff --git a/t/lib/Variable/Magic/TestDestroyRequired.pm b/t/lib/Variable/Magic/TestDestroyRequired.pm new file mode 100644 index 0000000..78c02f8 --- /dev/null +++ b/t/lib/Variable/Magic/TestDestroyRequired.pm @@ -0,0 +1,7 @@ +package Variable::Magic::TestDestroyRequired; + +use Variable::Magic; + +my $tag = Variable::Magic::wizard(); + +1;