Detectin mainloop integration

Alexander Larsson alexl at redhat.com
Thu Sep 27 02:17:47 PDT 2007


On Thu, 2007-09-27 at 09:33 +0200, Sebastian Dröge wrote:
> Am Donnerstag, den 27.09.2007, 09:26 +0200 schrieb Sebastian Dröge:
> > Am Donnerstag, den 27.09.2007, 09:06 +0200 schrieb Alexander Larsson:
> > > On Thu, 2007-09-27 at 07:31 +0200, Sebastian Dröge wrote:
> > > > Am Mittwoch, den 26.09.2007, 11:00 -0400 schrieb Havoc Pennington:
> > > > > Hi,
> > > > > 
> > > > > On 9/26/07, Alexander Larsson <alexl at redhat.com> wrote:
> > > > > > I totally agree. However, where is that place? A separate small
> > > > > > libdbus-glib-main.so?
> > > > > >
> > > > > 
> > > > > I don't see a lot of alternative - anyone have any other ideas?
> > > > 
> > > > ...and then having libdbus-glib-main.so be used in dbus-glib for the
> > > > mainloop integration? Sounds ok IMHO
> > > 
> > > Yeah, its probably the only possibility. Its "yet another shared lib"
> > > though. (And it has to be a shared lib so that multiple libs linking to
> > > it will not conflict on the integration.)
> > > 
> > > Does anyone want to do this?
> > 
> > If nobody else wants to do it I could do it. Would anything apart from
> > dbus_server_setup_with_g_main() and dbus_connection_setup_with_g_main()
> > be needed or wanted in that new library?

I think that is enought. Possibly people might want a way to remove the
mainloop integration for a connection (correctly refcounted so that it
works if multiple libs do this).

I'm trying to think what I disliked about the dbus-gmain code when
needing it in gvfs. I originally copied it in so that I could avoid
having the unstable dbus-glib dependency, but then I had to rewrite it
for some reason... /me desperately tries to remember

I think the problem I had was that dbus_connection_setup_with_g_main
owns the main context. Say you're using a custom mainloop + context pn a
thread, and then you do an async gio call on this thread, with this
mainloop. gvfs will then create a new peer-to-peer connection to the
gvfs daemon, and integrate this connection with the supplied main
context. However, when this thread later quits and unrefs of its main
context the dbus connection ows a ref to it, so its leaked, and the
connection isn't freed. What I wanted was that when the main context
goes away the dbus connection is un-integrated and we can free it.

Its easy to think of such cases where we want the dbus connection to
live during the lifetime of a mainloop. Is there ever a case where we
want the existance of a dbus connection to affect the lifetime of a
mainloop?

I don't think it ever really makes sense to integrate the shared session
bus with anything but the default main context, and then both objects
live forever, so that case is not very interesting. So, we have left
three cases:
1) Private connection integrated with default mainloop
2) Private connection integrated with a custom mainloop 
 a) We control the custom mainloop
 b) The custom mainloop was supplied from outside

(case 2b is the gvfs case)

I see three possible ownership solutions:
A) The integrated connection owns the mainloop
B) The mainloop owns the integrated connection
C) No ownership, both refs are weak

How do these solutions affect memory management in the three cases
above:

Solution A (connection owns mainloop):
1)  connection_new()
    integrate_connection()
    ... do work ...
    connection_unref()

2a) main_context_new()
    connection_new()
    integrate_connection()
    main_context_unref()
    ... do work ...
    connection_unref ()

2b) connection_new()
    integrate_connection(),
    ... do work ...
    App unrefs main context and stops mainloop:
        At this point the connection lives, but never gets
        any messages
    Library work is done:
        connection_unref()

Solution B (mainloop owns connection):
1)  connection_new ()
    integrate_connection ()
    connection_unref ()
    ... do work ...
    unintegrate_connection ()

2a) main_context_new()
    connection_new()
    integrate_connection()
    connection_unref ()
    ... do work ...
    main_context_unref()

2b) connection_new()
    integrate_connection(),
    connection_unref ()
    ... do work ...
    App unrefs main context and stops mainloop:
        This frees connection, and lib can catch finalize on it via
        dbus_connection_set_data
    Library work is done:
        unintegrate_connection()

Solution C (all weak refs)
1)  connection_new ()
    integrate_connection ()
    ... do work ...
    connection_unref ()

2a) main_context_new()
    connection_new()
    integrate_connection()
    ... do work ...
    connection_unref ()
    main_context_destroy ()

2b) connection_new()
    integrate_connection(),
    ... do work ...
    App unrefs main context and stops mainloop:
       connection will continue to live, but will
       be unintegrated and the mainloop can be freed.
       Library won't know anything changed and will not get
       any messages.
    Library work is done:
       connection_unref ()
       
Clearly, solution B is the only one that gives reasonable behaviour for
case 2b. However, choosing that does affect how the other cases are
handled. In particular, it requires the introduction of an untegrate
call so that case 1 can be handled.

This means the code has to be restructured a bit though. The gvfs code
actually uses solution C atm, which is not ideal. However, it is
probably a better base for an implementation of solution B.

> Hm, dbus-gmain.c is AFL/GPL licensed it seems. I guess it would be
> better for that library to be LGPL or MIT/X11, right? Does someone know
> who is to be contacted for
> 
>  * Copyright (C) 2002, 2003 CodeFactory AB
>  * Copyright (C) 2005 Red Hat, Inc.

I think LGPL is the best license for this. It already links to glib
which is LGPL, so that is not a problematic license for the users of the
library.

I think CodeFactory AB doesn't exist anymore, so that might be a bit
problematic. It is ok for us to relicence the Red Hat owned parts to
LGPL (or MIT if that is decided).




More information about the dbus mailing list