libmoonshot is not thread-safe

Bug #1575869 reported by Dan Breslau
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Moonshot ID Selector
Confirmed
Wishlist
Unassigned

Bug Description

The moonshot/ui/tests directory supports two tests, one of which is a test of multithreading in libmoonshot. This test usually fails, with failure modes including SIGSEGV, SIGABRT in the malloc library, or deadlock.

I believe the main problem is that libmoonshot is implemented using DBus-GLib. On this link : https://www.freedesktop.org/wiki/Software/DBusBindings/ , it says:

"DBus-GLib pretends to be thread-safe but is not. The object model is rubbish and is implemented much better in GDBus (above). The code is not maintained. Do not use it."

(note that freedesktop.org is the origin of dbus-glib!)

According to a note in libmoonshot/libmoonshot-dbus.c, dbus-glib was used due to the requirement to support Debian 6 (Squeeze), which comes with glib-2.24. The GDBus bindings were available in glib-2.26. Hence, if we drop support for Squeeze -- and I think this has already happened -- we can re-implement libmoonshot using GDBus. (I think the next-oldest OS we support is CentOS 6; Centos 6.7 comes with glib-2.28.)

If thread safety is a concern, we should make this a priority. (No pun intended :-)

----
I'm saving this additional note in case we continue with the current design of libmoonshot. It's probably not relevant if we do port to GDBus:

I first thought this function in libmoonshot/libmoonshot-dbus.c was the problem:

static DBusGProxy *get_dbus_proxy (MoonshotError **error)
{
    static DBusGProxy *dbus_proxy = NULL;
    static GStaticMutex init_lock = G_STATIC_MUTEX_INIT;

    g_static_mutex_lock (&init_lock);

    if (dbus_proxy == NULL) {
        /* Make sure GObject is initialised, in case we are the only user
         * of GObject in the process
         */
        g_type_init ();
        dbus_proxy = dbus_connect (error);
    }

    if (dbus_proxy != NULL)
        g_object_ref (dbus_proxy);

    g_static_mutex_unlock (&init_lock);

    return dbus_proxy;
}

Note that when the caller is done with the proxy, it calls g_object_unref(proxy), which is appropriate. But nothing prevents us from trying to use the proxy after the refcount drops to 0. But it turns out that the refcount never drops to 0 -- it's always at least 1, because we increment it even after we've first obtained the proxy from dbus-glib. I'm not sure if that extra ref was intentional, but it does prevent the refcount from dropping back to 0.

Revision history for this message
Mark Donnelly (meadmaker) wrote :

Fix will probably involve porting to GDBus

Changed in moonshot-ui:
importance: Undecided → Wishlist
status: New → Confirmed
Revision history for this message
Jennifer Richards (jennifer-k) wrote :

the reference counting in get_dbus_proxy() is correct. That function has a static handle on the DBusGProxy and the purpose here is to reuse that instance throughout the life of the process. That is the "extra ref" that Dan was concerned about---it's a reference owned by the static local variable (dbus_proxy).

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.