On 11.11.2013 01:09, Kevin Ryde wrote:
> How has this bit gone?  It definitely seems to do something unexpectedly
> bad.  How would you feel about reverting until the reason can be found?

I've had another look at this and now think that I understand what is
going on: Your MyContainer class derives from Gtk2::HBox and so, by
extension, from Glib::InitiallyUnowned.  The GObject underlying the
instance created by libgobject thus has only a single, floating
reference.  When marshalling this object for INIT_INSTANCE, another
reference is added, but the existing reference is kept in the floating
state (due to own=FALSE in the gperl_new_object() call in
gperl_type_instance_init()).

Without the call to $label->parent, this additional reference is simply
removed when INIT_INSTANCE exits (with the change under discussion) or
sometime later (without it), and the original floating reference
remains.  It later gets sunk in the marshalling of the MyContainer->new
call.

If you do, however, call $label->parent, then the marshalling code sees
that the underlying GObject has a floating reference and takes over
ownership of it (without adding a new reference).  The GObject now has
two references to it, one from $self and one from $parent.  With the
change under discussion, both of these get removed when INIT_INSTANCE
exits, leading to the destruction of the GObject.  Without the change,
the removal of the reference from $self to the GObject is delayed until
after the MyContainer->new call returned and $mycontainer added another
reference, thus preventing the destruction of the GObject.

So at this point, reverting the change (as in the attached patch) does
seem like a sensible thing to do.  This comes with a cost, however; for
example, Glib::Object::Introspection's test suite breaks.

So I have to ask: why are you calling $label->parent in INIT_INSTANCE
instead of simply using $self?
>From f46253bdb981eb569daeea93f43efcdc6db0c70b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Torsten=20Sch=C3=B6nfeld?= <kaffeeti...@gmx.de>
Date: Sun, 24 Nov 2013 21:45:45 +0100
Subject: [PATCH] WIP

---
 GType.xs | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/GType.xs b/GType.xs
index 471a4ee..dc0b3d9 100644
--- a/GType.xs
+++ b/GType.xs
@@ -1756,8 +1756,28 @@ gperl_type_instance_init (GObject * instance)
 	SV **slot;
 	g_assert (stash != NULL);
 
-	/* this SV will be freed below either via sv_2mortal or explicitly. */
-	obj = gperl_new_object (instance, FALSE);
+	/* we need to always create a wrapper, regardless of whether there is
+	 * an INIT_INSTANCE sub.  otherwise, the fallback mechanism in
+	 * GType.xs' SET_PROPERTY handler will not have an HV to store the
+	 * properties in.
+	 *
+	 * we also need to ensure that the wrapper we create is not immediately
+	 * destroyed when we return from gperl_type_instance_init.  otherwise,
+	 * instances of classes derived from GInitiallyUnowned might be
+	 * destroyed prematurely when code in INIT_INSTANCE manages to sink the
+	 * initial, floating reference.  example: in a container subclass'
+	 * INIT_INSTANCE, adding a child and then calling the child's
+	 * get_parent() method.  so we mortalize the wrapper before the
+	 * SAVETMPS/FREETMPS pair below.  this should ensure that the wrapper
+	 * survives long enough so that it is still intact when the call to the
+	 * Perl constructor returns.
+	 *
+	 * if we always sank floating references, or if we forbade doing things
+	 * as described in the example, we could simply free the SV before we
+	 * return from gperl_type_instance_init.  this would result in more
+	 * predictable reference counting. */
+	obj = sv_2mortal (gperl_new_object (instance, FALSE));
+
 	/* we need to re-bless the wrapper because classes change
 	 * during construction of an object. */
 	sv_bless (obj, stash);
@@ -1776,13 +1796,11 @@ gperl_type_instance_init (GObject * instance)
 		ENTER;
 		SAVETMPS;
 		PUSHMARK (SP);
-		XPUSHs (sv_2mortal (obj));	/* mortalize the SV */
+		XPUSHs (obj);
 		PUTBACK;
 		call_sv ((SV *)GvCV (*slot), G_VOID|G_DISCARD);
 		FREETMPS;
 		LEAVE;
-	} else {
-		SvREFCNT_dec (obj);		/* free the SV explicitly */
 	}
 }
 
-- 
1.8.1.2

_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtk-perl-list

Reply via email to