After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 669709 - Various cleanups and corrections
Various cleanups and corrections
Status: RESOLVED FIXED
Product: gjs
Classification: Bindings
Component: general
unspecified
Other All
: Normal normal
: ---
Assigned To: gjs-maint
gjs-maint
Depends on:
Blocks:
 
 
Reported: 2012-02-08 22:29 UTC by Jasper St. Pierre (not reading bugmail)
Modified: 2012-05-02 17:53 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
union: Clean up old, broken log statement (1.07 KB, patch)
2012-02-08 22:29 UTC, Jasper St. Pierre (not reading bugmail)
committed Details | Review
object: Properly manage memory for GObjects (2.93 KB, patch)
2012-02-08 22:29 UTC, Jasper St. Pierre (not reading bugmail)
reviewed Details | Review
object: Make sure that we properly update the counters for custom objects (1.06 KB, patch)
2012-02-08 22:29 UTC, Jasper St. Pierre (not reading bugmail)
committed Details | Review
function: Fix a few memory leaks (1.56 KB, patch)
2012-02-08 22:29 UTC, Jasper St. Pierre (not reading bugmail)
committed Details | Review

Description Jasper St. Pierre (not reading bugmail) 2012-02-08 22:29:05 UTC
While writing new GNOME Shell code, I came across a few memory corruptions,
crashes and leaks.
Comment 1 Jasper St. Pierre (not reading bugmail) 2012-02-08 22:29:07 UTC
Created attachment 207147 [details] [review]
union: Clean up old, broken log statement
Comment 2 Jasper St. Pierre (not reading bugmail) 2012-02-08 22:29:10 UTC
Created attachment 207148 [details] [review]
object: Properly manage memory for GObjects
Comment 3 Jasper St. Pierre (not reading bugmail) 2012-02-08 22:29:12 UTC
Created attachment 207150 [details] [review]
object: Make sure that we properly update the counters for custom objects

Since we initialize GObjects through construct properties, we need to
make sure that we don't get fooled and think that g_object_newv returned
a singleton.
Comment 4 Jasper St. Pierre (not reading bugmail) 2012-02-08 22:29:15 UTC
Created attachment 207151 [details] [review]
function: Fix a few memory leaks
Comment 5 Giovanni Campagna 2012-02-08 22:52:04 UTC
Review of attachment 207148 [details] [review]:

Uhm uhm uhm...
I didn't know GObject memory management was so screwed up - we used to valgrind gjs tests, rigth?

::: gi/object.c
@@ +891,3 @@
+        /* we should already have a ref */
+    }
+

I think it is wrong to have this special treatment here: it only applies to g_object_newv (which cannot be correctly marked (transfer none) or (transfer full) depending on the underlying constructor), not to other functions returning gobjects.

@@ -975,3 @@
-     * we just added, since refcount may drop to 1.
-     */
-    g_object_unref(gobj);

g_object_add_toggle_ref does g_object_ref internally, so you really need to pair the reference returned by g_object_newv (or the hacky workaround for a (transfer none) of a non floating object with a g_object_unref().

@@ -1786,3 @@
 
-        /* see the comment in init_object_instance() for this */
-        g_object_unref(gobj);

Same here, g_object_unref goes on pair with g_object_ref_sink, which ensures that we only ever handle non-floating objects.
(For floating objects, this brings down the ref_count to 1, which is correct since the only reference is the toggle reference. For non-floating objects, this simply pairs the above g_object_ref_sink, and actual refcounting correctness is handled by argument cleanup)
Comment 6 Giovanni Campagna 2012-02-08 22:53:28 UTC
Review of attachment 207147 [details] [review]:

I think this is fine.
(Does anyone make a real use of gjs_debug_lifecycle?)
Comment 7 Giovanni Campagna 2012-02-08 23:03:34 UTC
Review of attachment 207150 [details] [review]:

Uh! Good catch!
Comment 8 Giovanni Campagna 2012-02-08 23:05:01 UTC
Review of attachment 207151 [details] [review]:

Sure!
Comment 9 Giovanni Campagna 2012-02-08 23:09:18 UTC
Review of attachment 207148 [details] [review]:

::: gi/object.c
@@ +891,3 @@
+        /* we should already have a ref */
+    }
+

Ok, I see what you did now: if you inherit from GInitiallyUnowned or GtkWindow, you want the extra refs already when JS property code is called, so you can pass your object to C API freely.
The problem is that this adds an extra unbalanced ref for normal method calls. You may want to add a flag in associate_js_object (and a big big comment too)
Comment 10 Jasper St. Pierre (not reading bugmail) 2012-02-08 23:19:16 UTC
Review of attachment 207148 [details] [review]:

::: gi/object.c
@@ +891,3 @@
+        /* we should already have a ref */
+    }
+

By "normal method calls" do you mean a C API that returns a new GtkWindow?

In that case, we should be creating a new wrapper object through gjs_object_from_g_object, where we want to sink and ref the object so that we can properly set up a toggle ref, right?

@@ -975,3 @@
-     * we just added, since refcount may drop to 1.
-     */
-    g_object_unref(gobj);

Aha, I didn't realize g_object_add_toggle_ref added a ref internally. (But the existing code was still broken - if associate_js_gobject wasn't called, we'd be unreffing a ref we never added)
Comment 11 Giovanni Campagna 2012-02-08 23:44:15 UTC
(In reply to comment #10)
> Review of attachment 207148 [details] [review]:
> 
> ::: gi/object.c
> @@ +891,3 @@
> +        /* we should already have a ref */
> +    }
> +
> 
> By "normal method calls" do you mean a C API that returns a new GtkWindow?

A non-floating GtkWindow, or a floating GInitiallyUnowned, yes.
(It mostly happens with explicit constructor calls, but to the gjs eyes, those are just functions)

> In that case, we should be creating a new wrapper object through
> gjs_object_from_g_object, where we want to sink and ref the object so that we
> can properly set up a toggle ref, right?

Yes, but unless i misread it your patch removes that ref_sink. Also, gjs_object_from_g_object() calls associate_js_object(), so the latter must not mess with ref counts unless it's impossible to do otherwise.

> @@ -975,3 @@
> -     * we just added, since refcount may drop to 1.
> -     */
> -    g_object_unref(gobj);
> 
> Aha, I didn't realize g_object_add_toggle_ref added a ref internally. (But the
> existing code was still broken - if associate_js_gobject wasn't called, we'd be
> unreffing a ref we never added)

How is that possible? associate_js_gobject() is called right before that code (unless priv->gobj is not NULL, which means that something, somewhere, called it)
Comment 12 Jasper St. Pierre (not reading bugmail) 2012-02-08 23:59:48 UTC
(In reply to comment #11)
> (In reply to comment #10)
> > Review of attachment 207148 [details] [review] [details]:
> > 
> > ::: gi/object.c
> > @@ +891,3 @@
> > +        /* we should already have a ref */
> > +    }
> > +
> > 
> > By "normal method calls" do you mean a C API that returns a new GtkWindow?
> 
> A non-floating GtkWindow, or a floating GInitiallyUnowned, yes.
> (It mostly happens with explicit constructor calls, but to the gjs eyes, those
> are just functions)
> 
> > In that case, we should be creating a new wrapper object through
> > gjs_object_from_g_object, where we want to sink and ref the object so that we
> > can properly set up a toggle ref, right?
> 
> Yes, but unless i misread it your patch removes that ref_sink.

associate_g_object sinks the ref if it's floating.

> Also,
> gjs_object_from_g_object() calls associate_js_object(), so the latter must not
> mess with ref counts unless it's impossible to do otherwise.

The only time gjs_object_from_g_object is called is when we create a new wrapper, so we should sink any existing floating ref, and add a toggle ref, right?
Comment 13 Giovanni Campagna 2012-02-09 00:07:23 UTC
(In reply to comment #12)
> (In reply to comment #11)
> > (In reply to comment #10)
> > > Review of attachment 207148 [details] [review] [details] [details]:
> > > 
> > > ::: gi/object.c
> > > @@ +891,3 @@
> > > +        /* we should already have a ref */
> > > +    }
> > > +
> > > 
> > > By "normal method calls" do you mean a C API that returns a new GtkWindow?
> > 
> > A non-floating GtkWindow, or a floating GInitiallyUnowned, yes.
> > (It mostly happens with explicit constructor calls, but to the gjs eyes, those
> > are just functions)
> > 
> > > In that case, we should be creating a new wrapper object through
> > > gjs_object_from_g_object, where we want to sink and ref the object so that we
> > > can properly set up a toggle ref, right?
> > 
> > Yes, but unless i misread it your patch removes that ref_sink.
> 
> associate_g_object sinks the ref if it's floating.

True, but then it also adds an extra ref for GInitiallyUnowned that are not floating, which is wrong.

> > Also,
> > gjs_object_from_g_object() calls associate_js_object(), so the latter must not
> > mess with ref counts unless it's impossible to do otherwise.
> 
> The only time gjs_object_from_g_object is called is when we create a new
> wrapper, so we should sink any existing floating ref, and add a toggle ref,
> right?

Yes, but after sinking you need to unref, since you have two refs (one from ref_sink, the other from add_toggle_ref) and only want one. Problem is, after ref_sinking you don't know if the object was indeed floating or not, so you don't known if you need to unref.
At that point, ref_sink + unref always is simpler (for gjs_object_from_g_object()).
Comment 14 Jasper St. Pierre (not reading bugmail) 2012-02-10 15:24:19 UTC
Attachment 207147 [details] pushed as 6e179e9 - union: Clean up old, broken log statement
Attachment 207151 [details] pushed as 09c9964 - function: Fix a few memory leaks


I opted not to push the "Properly manage memory" commit -- it needs reworking, but I repurposed the "update the counters" commit to solve the crash with custom gobjects.