[patch] Fix locking for _dbus_connection_queue_received_message_link

Timo Teräs ext-timo.teras@nokia.com
Tue Jan 11 04:51:51 PST 2005


Hi,

I've bumped into locking problem when experimenting with multithreaded 
D-BUS program.

I got a dead lock with following backtrace:
#8  0xb7f855cf in pthread_mutex_lock () from /lib/tls/libc.so.6
#9  0xb7c307af in dbus_gmutex_lock (mutex=0xfffffffc) at dbus-gthread.c:96
#10 0xb7c11a96 in dbus_mutex_lock (mutex=0xb7a78b18) at dbus-threads.c:91
#11 0xb7bff986 in _dbus_connection_remove_timeout_locked (
     connection=0xffffffff, timeout=0xfffffffc) at dbus-connection.c:565
#12 0xb7bff6b4 in _dbus_connection_queue_received_message_link (
     connection=0x8060a20, link=0x8091520) at dbus-connection.c:345
#13 0xb7c12b60 in _dbus_transport_queue_messages (transport=0x805f4a8)
     at dbus-transport.c:868
#14 0xb7c136c1 in do_reading (transport=0x805f4a8) at 
dbus-transport-unix.c:689
#15 0xb7c1381e in unix_handle_watch (transport=0x805f4a8, watch=0x0,
     flags=3081210648) at dbus-transport-unix.c:743
#16 0xb7c126a0 in _dbus_transport_handle_watch (transport=0x805f4a8,
     watch=0x805f550, condition=1) at dbus-transport.c:580
#17 0xb7c001da in _dbus_connection_handle_watch (watch=0xfffffffc,
     condition=4294967292, data=0x8060a20) at dbus-connection.c:1060
#18 0xb7c1448c in dbus_watch_handle (watch=0x805f550, flags=1)
     at dbus-watch.c:595
#19 0xb7c2c577 in dbus_gsource_dispatch (source=0xfffffffc, callback=0,
     user_data=0x0, is_server=0) at dbus-gmain.c:232
#20 0xb7c2c5fe in gsource_connection_dispatch (source=0x8062038,
     callback=0xfffffffc, user_data=0xfffffffc) at dbus-gmain.c:254
#21 0xb7b9c902 in g_main_depth () from /usr/lib/libglib-2.0.so.0
#22 0xb7b9d9f8 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#23 0xb7b9dd30 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#24 0xb7b9e373 in g_main_loop_run () from /usr/lib/libglib-2.0.so.0

I also added some debugging prints and realized that CONNECTION_LOCK is 
called twice in this code path. The connection lock is first acquired in 
_dbus_connection_handle_watch().The second time comes when 
_dbus_connection_queue_received_message_link() calls 
_dbus_connection_remove_timeout_locked() which tries to also acquire the 
connection lock and deadlocks (GMutexes aren't recursive).

If I'm not mistaken the _dbus_connection_queue_received_message_link() 
will always be called from the _dbus_connection_handle_watch() so the 
connection lock is always held when entering that function. So, I 
changed the call from _dbus_connection_remove_timeout_locked() to 
_dbus_connection_remove_timeout(). Patch attached.

It also seems this was the only place where the _remove_timeout_locked 
was called so it is not used anymore. The second version of patch 
includes also removal of that function.

Cheers,
   Timo
-------------- next part --------------
Index: dbus/dbus-connection.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-connection.c,v
retrieving revision 1.86
diff -u -r1.86 dbus-connection.c
--- dbus/dbus-connection.c	27 Nov 2004 07:30:22 -0000	1.86
+++ dbus/dbus-connection.c	11 Jan 2005 12:45:18 -0000
@@ -224,8 +224,6 @@
 #endif 
 };
 
-static void               _dbus_connection_remove_timeout_locked             (DBusConnection     *connection,
-                                                                              DBusTimeout        *timeout);
 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
                                                                               DBusDispatchStatus  new_status);
@@ -349,8 +347,8 @@
       if (pending != NULL)
 	{
 	  if (pending->timeout_added)
-	    _dbus_connection_remove_timeout_locked (connection,
-                                                    pending->timeout);
+	    _dbus_connection_remove_timeout (connection,
+                                             pending->timeout);
 
 	  pending->timeout_added = FALSE;
 	}
@@ -594,15 +592,6 @@
 				       timeout);
 }
 
-static void
-_dbus_connection_remove_timeout_locked (DBusConnection *connection,
-					DBusTimeout    *timeout)
-{
-  CONNECTION_LOCK (connection);
-  _dbus_connection_remove_timeout (connection, timeout);
-  CONNECTION_UNLOCK (connection);
-}
-
 /**
  * Toggles a timeout and notifies app via connection's
  * DBusTimeoutToggledFunction if available. It's an error to call this
-------------- next part --------------
Index: dbus/dbus-connection.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-connection.c,v
retrieving revision 1.86
diff -u -r1.86 dbus-connection.c
--- dbus/dbus-connection.c	27 Nov 2004 07:30:22 -0000	1.86
+++ dbus/dbus-connection.c	11 Jan 2005 12:31:59 -0000
@@ -349,8 +349,8 @@
       if (pending != NULL)
 	{
 	  if (pending->timeout_added)
-	    _dbus_connection_remove_timeout_locked (connection,
-                                                    pending->timeout);
+	    _dbus_connection_remove_timeout (connection,
+                                             pending->timeout);
 
 	  pending->timeout_added = FALSE;
 	}


More information about the dbus mailing list