develooper Front page | perl.perl5.porters | Postings from March 2017

Re: [perl #32714] Objects destroyed in the wrong order during globaldestruction

Thread Previous | Thread Next
Dave Mitchell
March 16, 2017 11:08
Re: [perl #32714] Objects destroyed in the wrong order during globaldestruction
Message ID:
On Tue, Mar 14, 2017 at 05:20:38AM -0700, Nick Wellnhofer via RT wrote:
> On Tue, 14 Mar 2017 01:46:17 -0700, davem wrote:
> > Can you provide a short, self-contained perl program which demonstrates
> > the bug, and which would be fixed by why you propose above; just so that 
> > we can be sure we're all discussing the same issue.
> I already did so here:

Ah sorry, I completely failed to spot that when I looked.

> I would expect $our1->DESTROY to be run before $our2->DESTROY because
> $our1 holds a reference to $our2. But (at least with Perl 5.22.1), the
> DESTROY method is first invoked on $our2.

> I realize that this problem is harder than I initially thought. But I
> think it could be solved by deferring freeing of package vars during
> global destruction. So if a refcount drops to zero, DESTROY is invoked,
> the object is not freed, but refcounts of other objects that are
> referred to are decreased. In other words, you simulate freeing an
> object just for refcount side effects. Then, in a second pass, DESTROY
> is invoked on objects that still have a refcount (because of circular
> references or refcount leaks).

Note that the effect demonstrated by your code is not caused by global vars
being freed - in fact during both calls to DESTROY, $our1 and $our2 exist
and have a reference count >= 1.

What is actually happening is that at that point during global
destruction, perl is linearly scanning SV arenas looking for any RV which
points to an object. Each such RV is undeffed (*not* freed), which may
trigger a destructor call on the now not-so-referred-to object.

So its a bit like your code having this in it:

    END { undef $our1; undef $our2 }

except that the order is non-deterministic, so it could equally as well be

    END { undef $our2; undef $our1 }

and note that its also unrelated to package vars: it's *any* RV that can
be found (including anonymous ones) which gets zapped, in any order. So
for example:

    our $x;
    $x->{l1}{l2}{l3}{l4} = 1;

(where each hash is blessed) might have a destruction equivalent to any of

    END { undef $x->{l1}{l2}; undef $x }
    END { undef $x }
    END { undef $x->{l1}{l2}{l3}; undef $x->{l1}; undef $x }
    ... etc ...

Now having explained all that, I don't really understand your proposal
above. Given that package vars *aren't* freed at that point during global
destruction, could you update and clarify your proposal?

In England there is a special word which means the last sunshine
of the summer. That word is "spring".

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About