<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from rtf -->
<style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<font face="Arial, sans-serif" size="2">
<div>Hi, Everyone:</div>
<div>&nbsp;</div>
<div>I recently played with dbus-glib in multi-thread environment and found following 2 race conditions in dbus-glib. I didn't find them in dbus mailing list archives so put here for you review and hope get some suggestions to solve them. </div>
<div>I'm new in dbus, glib and dbus-glib programming so please correct me in case any misunderstanding. Thanks! </div>
<div>&nbsp;</div>
<div>1. See code at dbus-gproxy.c:dbus_g_proxy_end_call_internal: </div>
<div>&nbsp; pending = g_hash_table_lookup (priv-&gt;pending_calls, GUINT_TO_POINTER (call_id));</div>
<div>&nbsp; dbus_pending_call_block (pending);</div>
<div>The pending returned can be NULL and the function dbus_pending_call_block will trigger assert and then abort the program. </div>
<div>&nbsp;</div>
<div>The race condition exists at below scenario: </div>
<div>a. Thread A create a proxy through dbus_g_proxy_new_for_name and create a pending call &quot;GetNameOwner&quot;. That's done in dbus-glib internal. </div>
<div>b. Then Thread A uses the dbus_g_proxy_call and finishes a call. When it unref the proxy, it will call dbus_g_proxy_cancel_call to remove the &quot;GetNameOwner&quot; pending call. </div>
<div>c. But before the Thread A really cancel the call, Thread B, which has a mainloop has received the reply for the &quot;GetNameOwner&quot; call and then call got_name_owner_cb. The got_name_owner_cb calls dbus_g_proxy_end_call_internal and the pending can not be
found. Then the code above will trigger assert(pending!=NULL) in dbus_pending_call_block;</div>
<div>&nbsp;</div>
<div>I did hack to return FALSE when pending returned is NULL could bypass that bug. But I don't what negative impacts will be. </div>
<div>&nbsp;</div>
<div>2. See code at dbus-proxy.c:dbus_g_proxy_manager_get</div>
<div>&nbsp; manager = dbus_connection_get_data (connection, g_proxy_manager_slot);</div>
<div>&nbsp; if (manager != NULL)</div>
<div>&nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbus_connection_free_data_slot (&amp;g_proxy_manager_slot);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbus_g_proxy_manager_ref (manager);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_static_mutex_unlock (&amp;connection_g_proxy_lock);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return manager;</div>
<div>&nbsp;&nbsp;&nbsp; }</div>
<div>The manager returned from dbus_connection_get_data doesn't have manager-&gt;refcount increased before it calls dbus_g_proxy_manager_ref. Between these two calls, other thread is able to decrease manager-&gt;refcount to 0 and free the manager. Then the manager
returned becomes an invalid pointer. </div>
<div>&nbsp;</div>
<div>The race condition exists at below scenario:</div>
<div>a. Thread A wants to create a proxy, it will calls dbus_g_proxy_manager_register to register the proxy to the proxy manager. My understanding is there is only one proxy manager instance across all threads in the same process. Thread A will call dbus_g_proxy_manager_ref
(in dbus_g_proxy_manager_get) to increase the reference count to the manager. </div>
<div>b. In function dbus_g_proxy_manager_ref, it will wait for manager-&gt;lock. But the manager-&gt;lock is hold by Thread B and manager-&gt;refcount is 1 now so the reference count will not be increased till Thread B release the lock.&nbsp; </div>
<div>c. Thread B just finished all calls and then call dbus_g_proxy_manager_dispose, which will call dbus_g_proxy_manager_unref. Then the manager-&gt;refcount becomes 0. Then the Thread B calls dbus_g_proxy_manager_unref and directly frees the manager. </div>
<div>d. After Thread B release the manager-&gt;lock. Thread A was scheduled but the manager pointer is an invalid pointer. </div>
<div>&nbsp;</div>
<div>I have not found good way to solve that problem. Personally I think probably we need some big changes. </div>
<div>&nbsp;</div>
<div>Thanks</div>
<div>Jackie (Weihua) Wu</div>
<div>Intel Opensource Technology Center</div>
<div>Intel China Research Center</div>
<div>(inet)8-758-1963 </div>
<div>(o) 86-10-82171963</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
</font>
</body>
</html>