GDBusConnection: Avoid callbacks on finalized connection

Turns out that GDBusWorker will issue callbacks (in its own thread)
even after g_dbus_worker_stop() has been called. This would rarely
happen (and unreffing a connection is even rarer) so only saw this bug
occasionally when running the gdbus-connection test case in a loop.

Fix up this issue by maintaining a set of GDBusConnection objects that
are currently "alive" and do nothing in the callbacks if the passed
user_data pointer is not in this set.

Also attempted to fix up a race condition with
_g_object_wait_for_single_ref_do() and its use of GObject toggle
references - for now, just resort to busy waiting, thereby
sidestepping the toggle reference mess altogether.

Signed-off-by: David Zeuthen <davidz@redhat.com>
This commit is contained in:
David Zeuthen
2010-09-23 15:10:50 -04:00
committed by Ryan Lortie
parent 55ef8b0d89
commit c4081f9abd
4 changed files with 115 additions and 22 deletions

View File

@@ -1443,22 +1443,14 @@ _g_dbus_worker_new (GIOStream *stream,
/* ---------------------------------------------------------------------------------------------------- */
/* This can be called from any thread - frees worker - guarantees no callbacks
* will ever be issued again
/* This can be called from any thread - frees worker. Note that
* callbacks might still happen if called from another thread than the
* worker - use your own synchronization primitive in the callbacks.
*/
void
_g_dbus_worker_stop (GDBusWorker *worker)
{
/* If we're called in the worker thread it means we are called from
* a worker callback. This is fine, we just can't lock in that case since
* we're already holding the lock...
*/
if (g_thread_self () != worker->thread)
g_mutex_lock (worker->read_lock);
worker->stopped = TRUE;
if (g_thread_self () != worker->thread)
g_mutex_unlock (worker->read_lock);
g_cancellable_cancel (worker->cancellable);
_g_dbus_worker_unref (worker);
}