diff options
author | David Mitchell <davem@iabyn.com> | 2010-09-18 23:01:54 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2010-09-20 08:16:12 +0100 |
commit | 57ef47cc7bcd1b57927d5010f363ccaa10f1d990 (patch) | |
tree | c342caf5d8e9639a4b7d484c05606250c19904da /intrpvar.h | |
parent | fb85c0447bf1d343a9b4d4d7075184aeb4c9ae46 (diff) | |
download | perl-57ef47cc7bcd1b57927d5010f363ccaa10f1d990.tar.gz |
stop do_clean_named_objs() leaving dangling refs
Currently perl does 3 major scans of the SV arenas, so the action of
perl_destroy() is a bit like this:
for (all arena SVs) {
if (its a ref to an object)
undef the ref (and thus probably free the object)
}
for (all arena SVs) {
if (it's a typeglob and at least one of its slots holds an object) {
set SVf_BREAK on the gv
SvREFCNT_dec(gv)
}
}
return if $PERL_DESTRUCT_LEVEL < 1;
PL_in_clean_all = 1
for (all arena SVs) {
set SVf_BREAK on the sv
SvREFCNT_dec(sv)
}
The second scan is problematic, in that by randomly zapping GVs, it can
leave dangling pointers to freed GVs. This is while perl-level destructors
may still be called, meaning perl users can see corrupted state.
Note also that at this point PL_in_clean_all hasn't been set, so sv_free()
may put out 'Attempt to free unreferenced scalar' warnings.
This commit fixes this by only freeing the affected slots of the GV,
rather than freeing the GV itself. Thus makes it more like the first pass,
which undefs RVs, and ensures no dangling refs.
Diffstat (limited to 'intrpvar.h')
-rw-r--r-- | intrpvar.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/intrpvar.h b/intrpvar.h index 0fd956d4da..4a7d867904 100644 --- a/intrpvar.h +++ b/intrpvar.h @@ -465,7 +465,7 @@ PERLVAR(IDBcv, CV *) /* from perl.c */ PERLVARI(Igeneration, int, 100) /* from op.c */ PERLVARI(Iin_clean_objs,bool, FALSE) /* from sv.c */ -PERLVARI(Iin_clean_all, bool, FALSE) /* from sv.c */ +PERLVARI(Iin_clean_all, bool, FALSE) /* ptrs to freed SVs now legal */ PERLVAR(Inomemok, bool) /* let malloc context handle nomem */ PERLVARI(Isavebegin, bool, FALSE) /* save BEGINs for compiler */ |