stop do_clean_named_objs() leaving dangling refs
authorDavid Mitchell <davem@iabyn.com>
Sat, 18 Sep 2010 22:01:54 +0000 (23:01 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 20 Sep 2010 07:16:12 +0000 (08:16 +0100)
commit57ef47cc7bcd1b57927d5010f363ccaa10f1d990
treec342caf5d8e9639a4b7d484c05606250c19904da
parentfb85c0447bf1d343a9b4d4d7075184aeb4c9ae46
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.
intrpvar.h
sv.c
t/op/ref.t