diff options
author | David Mitchell <davem@iabyn.com> | 2010-09-19 12:33:04 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2010-09-20 08:16:12 +0100 |
commit | ca556bcdca736b2f85c11650c70b2371169c0225 (patch) | |
tree | a7a82e95d79fd49df1836753caa898b9e2a6bb6d /perl.c | |
parent | b2ea9a00b30eb5881b863d7239dd6a3721e73136 (diff) | |
download | perl-ca556bcdca736b2f85c11650c70b2371169c0225.tar.gz |
[perl #40389] perl_destruct() leaks PL_defstash
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.
Diffstat (limited to 'perl.c')
-rw-r--r-- | perl.c | 2 |
1 files changed, 2 insertions, 0 deletions
@@ -1042,6 +1042,8 @@ perl_destruct(pTHXx) /* 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); |