]> git.vpit.fr Git - perl/modules/Variable-Magic.git/commitdiff
Properly unmortalize the wizard after removing it from the global hash
authorVincent Pit <vince@profvince.com>
Thu, 26 Mar 2009 19:07:59 +0000 (20:07 +0100)
committerVincent Pit <vince@profvince.com>
Thu, 26 Mar 2009 19:07:59 +0000 (20:07 +0100)
MANIFEST
Magic.xs
t/15-self.t
t/lib/Variable/Magic/TestDestroyRequired.pm [new file with mode: 0644]

index d64a46480d408b3e825bbf7f9ecb4d82019468c2..dadd63aaae5c8f0bd59f57d6a71763c454c70213 100644 (file)
--- 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
index 0bd0bfd2ba1d45668266d373b0d04f0c4f884abd..f9587ab60995c8bc1b322220671d55f27ac534bc 100644 (file)
--- 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));
index 700cb17d714ff582cc1a850053f31731cef5e244..504c4b217bfb46499b8bb0c321d87534df07d47b 100644 (file)
@@ -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 (file)
index 0000000..78c02f8
--- /dev/null
@@ -0,0 +1,7 @@
+package Variable::Magic::TestDestroyRequired;
+
+use Variable::Magic;
+
+my $tag = Variable::Magic::wizard();
+
+1;