First patch from:
Brandon Black [Tue, 26 Jun 2007 11:05:31 +0000 (06:05 -0500)]
Subject: Re: [perl #43357] *DESTROY = sub {} at runtime
From: "Brandon Black" <blblack@gmail.com>
Message-ID: <84621a60706260905x2da6eaf1x4bd7d5223951e52@mail.gmail.com>

Fix problem recently introduced with loosing a DESTROY when redefined
at runtime.

p4raw-id: //depot/perl@31472

gv.c
t/mro/basic.t

diff --git a/gv.c b/gv.c
index 8f98f00..9751afa 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -1509,9 +1509,10 @@ Perl_Gv_AMupdate(pTHX_ HV *stash)
   dVAR;
   MAGIC* const mg = mg_find((SV*)stash, PERL_MAGIC_overload_table);
   AMT amt;
+  const struct mro_meta* stash_meta = HvMROMETA(stash);
   U32 newgen;
 
-  newgen = PL_sub_generation + HvMROMETA(stash)->cache_gen;
+  newgen = PL_sub_generation + stash_meta->pkg_gen + stash_meta->cache_gen;
   if (mg) {
       const AMT * const amtp = (AMT*)mg->mg_ptr;
       if (amtp->was_ok_am == PL_amagic_generation
@@ -1638,11 +1639,13 @@ Perl_gv_handler(pTHX_ HV *stash, I32 id)
     MAGIC *mg;
     AMT *amtp;
     U32 newgen;
+    struct mro_meta* stash_meta;
 
     if (!stash || !HvNAME_get(stash))
         return NULL;
 
-    newgen = PL_sub_generation + HvMROMETA(stash)->cache_gen;
+    stash_meta = HvMROMETA(stash);
+    newgen = PL_sub_generation + stash_meta->pkg_gen + stash_meta->cache_gen;
 
     mg = mg_find((SV*)stash, PERL_MAGIC_overload_table);
     if (!mg) {
index 0871d19..b514a04 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-require q(./test.pl); plan(tests => 12);
+require q(./test.pl); plan(tests => 18);
 
 {
     package MRO_A;
@@ -69,3 +69,59 @@ is(eval { MRO_N->testfunc() }, 123);
 # XXX TODO (when there's a way to backtrack through a glob's aliases)
 # push(@MRO_M::ISA, 'MRO_TestOtherBase');
 # is(eval { MRO_N->testfunctwo() }, 321);
+
+# Simple DESTROY Baseline
+{
+    my $x = 0;
+    my $obj;
+
+    {
+        package DESTROY_MRO_Baseline;
+        sub new { bless {} => shift }
+        sub DESTROY { $x++ }
+
+        package DESTROY_MRO_Baseline_Child;
+        our @ISA = qw/DESTROY_MRO_Baseline/;
+    }
+
+    $obj = DESTROY_MRO_Baseline->new();
+    undef $obj;
+    is($x, 1);
+
+    $obj = DESTROY_MRO_Baseline_Child->new();
+    undef $obj;
+    is($x, 2);
+}
+
+# Dynamic DESTROY
+{
+    my $x = 0;
+    my $obj;
+
+    {
+        package DESTROY_MRO_Dynamic;
+        sub new { bless {} => shift }
+
+        package DESTROY_MRO_Dynamic_Child;
+        our @ISA = qw/DESTROY_MRO_Dynamic/;
+    }
+
+    $obj = DESTROY_MRO_Dynamic->new();
+    undef $obj;
+    is($x, 0);
+
+    $obj = DESTROY_MRO_Dynamic_Child->new();
+    undef $obj;
+    is($x, 0);
+
+    no warnings 'once';
+    *DESTROY_MRO_Dynamic::DESTROY = sub { $x++ };
+
+    $obj = DESTROY_MRO_Dynamic->new();
+    undef $obj;
+    is($x, 1);
+
+    $obj = DESTROY_MRO_Dynamic_Child->new();
+    undef $obj;
+    is($x, 2);
+}