This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #40389] perl_destruct() leaks PL_defstash
authorDavid Mitchell <davem@iabyn.com>
Sun, 19 Sep 2010 11:33:04 +0000 (12:33 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 20 Sep 2010 07:16:12 +0000 (08:16 +0100)
With PERL_DESTRUCT_LEVEL >= 1, PL_defstash is explicitly freed,
but doesn't actually get freed at that point due to a reference loop
between %:: and *::. Break that loop to ensure that PL_defstash gets freed
at that point. Actually, its not as serious as it sounds, as it would get
freed a bit later anyway by sv_clean_all(), but this new way has these
benefits:

* it gets freed where you expect it to be
* it gets freed cleanly, rather than by the more brutal sv_clean_all()
  (which can leave dangling pointers to freed SVs)
* since its freed while *not* under the influence of
  PL_in_clean_all = TRUE, it's more likely to flag up bugs related to
  double-freeing etc. Indeed, the two previous commits to this are a
  result of that.

perl.c

diff --git a/perl.c b/perl.c
index a04cfd6..860cdfc 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -1042,6 +1042,8 @@ perl_destruct(pTHXx)
     /* Prepare to destruct main symbol table.  */
 
     hv = PL_defstash;
     /* Prepare to destruct main symbol table.  */
 
     hv = PL_defstash;
+    /* break ref loop  *:: <=> %:: */
+    (void)hv_delete(hv, "main::", 6, G_DISCARD);
     PL_defstash = 0;
     SvREFCNT_dec(hv);
     SvREFCNT_dec(PL_curstname);
     PL_defstash = 0;
     SvREFCNT_dec(hv);
     SvREFCNT_dec(PL_curstname);