Front page | perl.perl5.porters |
Postings from December 2011
Object destruction changes in 5.15 break Gtk2
Thread Next
From:
Torsten Schoenfeld
Date:
December 10, 2011 10:45
Subject:
Object destruction changes in 5.15 break Gtk2
Message ID:
4EE3A8D8.9020104@gmx.de
[Sorry for getting to this so late.]
The changes to object destruction described in
<https://rt.perl.org/rt3/Public/Bug/Display.html?id=36347> and
<http://perl5.git.perl.org/perl.git/commitdiff/4155e4fe> are known to
break Gtk2 and friends (which I am the maintainer of). I'd like to fix
things so that we will work with 5.16, but I'm unsure what the best way
to do that is. Let me describe the problem.
Gtk2 uses Glib for most of the heavy lifting, specifically:
Glib::Object. Conceptually, Glib::Object wraps ref-counted C objects
(GObjects) by permanently associating HVs to them and then handing out
references to the HVs. If we encounter a GObject for the first time, we
create a new HV and a new RV pointing to the HV and increase the
GObject's ref-count. The RV gets handed to user code. If we encounter
that GObject again later, we look up its associated HV, increase the
GObject's ref-count, and return a new reference to this existing HV.
Thus, user code always sees references to the same HV and can use it to
store and retrieve data.
[GObject → SV:
<http://git.gnome.org/browse/perl-Glib/tree/GObject.xs#n804>. SV →
GObject: <http://git.gnome.org/browse/perl-Glib/tree/GObject.xs#n958>.]
Now, if such an RV goes out of scope, we decrease the GObject's
ref-count. And since normally the HV would also be destroyed, but we
want to keep it around, we *in*crement its ref-count in DESTROY and put
it in an "undead" state. This way, even if all user-visible references
to the HV have been dropped, we can still fetch and "revive" the correct
HV if we see the GObject again. If the actual GObject is destroyed, we
get a callback and destroy the HV.
[DESTROY: <http://git.gnome.org/browse/perl-Glib/tree/GObject.xs#n1207>.
Callback for GObject destruction:
<http://git.gnome.org/browse/perl-Glib/tree/GObject.xs#n769>.]
In perl <= 5.14, this worked fine in that we got a call to DESTROY for
each RV we handed out. In blead now, during global destruction, we
actually get an additional call of DESTROY for each HV. Presumably, the
changes mentioned above now also see the "undead" HV, create a temporary
RV for it and invoke DESTROY on it. That leads to an extra decrement of
the GObject's ref-count, often resulting in segfaults.
So it seems that we made an implicit assumption: we will not get DESTROY
calls on HVs which have no RVs pointing to them. That seems to not hold
anymore. So, my question is: is that assumption unreasonable? If so,
what should we do to fix our code?
Thread Next