Bug 36811 - memory leak when objects are automatically unregistered
Summary: memory leak when objects are automatically unregistered
Status: RESOLVED FIXED
Alias: None
Product: dbus
Classification: Unclassified
Component: GLib (show other bugs)
Version: unspecified
Hardware: Other All
: medium normal
Assignee: Simon McVittie
QA Contact: John (J5) Palmieri
URL: http://cgit.collabora.co.uk/git/user/...
Whiteboard: NB#252114, mostly r+ from KA
Keywords: patch
Depends on: 32087 36793
Blocks:
  Show dependency treegraph
 
Reported: 2011-05-03 10:50 UTC by Simon McVittie
Modified: 2011-05-27 04:00 UTC (History)
1 user (show)

See Also:
i915 platform:
i915 features:


Attachments
[PATCH 1/5] dbus-gobject: wrap the GSList of registrations in a simple struct (6.30 KB, patch)
2011-05-04 05:07 UTC, Simon McVittie
Details | Splinter Review
[PATCH 2/5] dbus_g_connection_register_g_object: attach ObjectExport first (2.53 KB, patch)
2011-05-04 05:07 UTC, Simon McVittie
Details | Splinter Review
[PATCH 3/5] dbus_g_connection_register_g_object: only hook onto signals on first use (3.63 KB, patch)
2011-05-04 05:08 UTC, Simon McVittie
Details | Splinter Review
[PATCH 4/5] Add a regression test for removing all registrations and starting again (3.16 KB, patch)
2011-05-04 05:08 UTC, Simon McVittie
Details | Splinter Review
[PATCH 5/5] dbus-gobject: move weakref to ObjectExport, with ObjectRegistration pointing there (6.30 KB, patch)
2011-05-04 05:08 UTC, Simon McVittie
Details | Splinter Review
[bonus patch] dbus-gobject: check various preconditions for methods (3.35 KB, patch)
2011-05-10 04:22 UTC, Simon McVittie
Details | Splinter Review

Description Simon McVittie 2011-05-03 10:50:01 UTC
+++ This bug was initially created as a clone of Bug #36793 +++

If you do this:

* create a GObject
* export it on D-Bus (at n >= 1 object paths)
* unref the object enough times that it is freed

there should be no leak.

What actually happens is:

* each object registration "o" has a weak ref which results in a
  call to object_registration_object_died
* object_registration_object_died sets o->object to NULL
* object_registration_object_died calls dbus_connection_unregister_object_path
* this results in a call to object_registration_unregistered
* which calls object_registration_free
* which does not remove the dbus_glib_object_registrations qdata
  from the object, because the object has already been freed at this point
  so it's too late (and also because o->object is NULL)

Because the object registrations are already qdata, we shouldn't really need a weak ref at all...
Comment 1 Simon McVittie 2011-05-04 05:07:16 UTC
Created attachment 46316 [details] [review]
[PATCH 1/5] dbus-gobject: wrap the GSList of registrations in a  simple struct

For simplicity, the ObjectExport struct isn't freed until the object
is actually destroyed, even if there are no more registrations.
Comment 2 Simon McVittie 2011-05-04 05:07:36 UTC
Created attachment 46317 [details] [review]
[PATCH 2/5] dbus_g_connection_register_g_object: attach ObjectExport  first

This means we no longer need the unnecessarily subtle "steal and put back"
pattern.
Comment 3 Simon McVittie 2011-05-04 05:08:01 UTC
Created attachment 46318 [details] [review]
[PATCH 3/5] dbus_g_connection_register_g_object: only hook onto signals on first use

This fixes a bug in which an empty list of registrations was considered
to be synonymous with the object never having been exported, resulting
in this failure mode:
 
* register object at n locations
  - the first time, export_signals() is called
* unregister all of those locations
* register object at a new location
  - export_signals() is wrongly called again
* emit a signal
  - the D-Bus signal gets emitted twice
Comment 4 Simon McVittie 2011-05-04 05:08:27 UTC
Created attachment 46319 [details] [review]
[PATCH 4/5] Add a regression test for removing all registrations and starting again

This has been confirmed to fail when the previous commit is reverted.
Comment 5 Simon McVittie 2011-05-04 05:08:53 UTC
Created attachment 46320 [details] [review]
[PATCH 5/5] dbus-gobject: move weakref to ObjectExport, with ObjectRegistration pointing there

This has the following results: 

* each exported object only needs one weak ref to itself, however many
  times it is registered
* because the ObjectRegistration now points to the ObjectExport,
  it can always remove itself from the list of registrations even if the
  actual object has been disposed, avoiding a leak (fd.o #36811)
Comment 6 Cosimo Alfarano 2011-05-04 09:04:17 UTC
Review of attachment 46316 [details] [review]:

Not a reviewer, but seems sane to me.

::: dbus/dbus-gobject.c
@@ +2507,3 @@
                                        GObject *object)
 {
+  ObjectExport *oe = g_object_get_data (object, "dbus_glib_object_registrations");

Does g_object_get_data not complain when @object is not a GObject?

Although, it wasn't checked before also.

@@ +2567,3 @@
    * the object. */
+  oe = g_object_steal_data (object, "dbus_glib_object_registrations");
+

As before, @object is not checked and it's a public method.

It does not change much though, as there will be some assertion in _steal_data doing the same.
Comment 7 Cosimo Alfarano 2011-05-04 09:09:01 UTC
Review of attachment 46317 [details] [review]:

Not a reviewer, but OK for me
Comment 8 Cosimo Alfarano 2011-05-06 03:11:14 UTC
Review of attachment 46318 [details] [review]:

Again, no hat, but sane to me
Comment 9 Cosimo Alfarano 2011-05-06 03:22:54 UTC
Review of attachment 46319 [details] [review]:

test OK
Comment 10 Cosimo Alfarano 2011-05-06 07:24:35 UTC
Review of attachment 46320 [details] [review]:

OK to me
Comment 11 Simon McVittie 2011-05-06 07:33:10 UTC
(In reply to comment #6)
> Does g_object_get_data not complain when @object is not a GObject?
> 
> Although, it wasn't checked before also.
...
> As before, @object is not checked and it's a public method.

You're right, that'd be an improvement, but it's not a regression, and I think one of my other branches might fix it already?

Any thoughts on the patches I did for the two bugs blocking this one?
Comment 12 Cosimo Alfarano 2011-05-06 09:14:22 UTC
> Any thoughts on the patches I did for the two bugs blocking this one?


All fine. Comments published for each bugs.
Comment 13 Simon McVittie 2011-05-10 04:22:20 UTC
Created attachment 46538 [details] [review]
[bonus patch] dbus-gobject: check various preconditions for methods

Cosimo pointed out that there was a missing precondition check, although that wasn't a regression. I went through all of the public API in dbus-gobject.c adding such checks.
Comment 14 Simon McVittie 2011-05-27 04:00:00 UTC
Fixed in git for 0.94, based on review from Cosimo and no objections from the reviewer group.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.