[glib/wip/gcleanup] gdbusprivate: Shutdown shared worker thread correctly
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/gcleanup] gdbusprivate: Shutdown shared worker thread correctly
- Date: Sat, 9 Nov 2013 19:56:26 +0000 (UTC)
commit dd7da0eb1234f5e0f843613d003764bbec93576f
Author: Stef Walter <stefw gnome org>
Date: Sat Nov 9 20:16:26 2013 +0100
gdbusprivate: Shutdown shared worker thread correctly
Both when idle and during cleanup.
gio/gdbusprivate.c | 65 ++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 53 insertions(+), 12 deletions(-)
---
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index 785a0c0..75886a4 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -43,6 +43,7 @@
#include "gsocketcontrolmessage.h"
#include "gsocketconnection.h"
#include "gsocketoutputstream.h"
+#include "gthread.h"
#ifdef G_OS_UNIX
#include "gunixfdmessage.h"
@@ -276,6 +277,10 @@ gdbus_shared_thread_func (gpointer user_data)
g_main_context_push_thread_default (data->context);
g_main_loop_run (data->loop);
+
+ /* Process any remaining stragglers */
+ while (g_main_context_iteration (data->context, FALSE));
+
g_main_context_pop_thread_default (data->context);
release_required_types ();
@@ -285,13 +290,40 @@ gdbus_shared_thread_func (gpointer user_data)
/* ---------------------------------------------------------------------------------------------------- */
+G_LOCK_DEFINE_STATIC (shared_thread_data);
+static gpointer shared_thread_data = NULL;
+
+static void
+_g_dbus_shared_thread_wait_and_free (SharedThreadData *data)
+{
+ g_main_loop_quit (data->loop);
+ g_thread_join (data->thread);
+ g_main_loop_unref (data->loop);
+ g_main_context_unref (data->context);
+
+ g_free (data);
+}
+
+static void
+_g_dbus_shared_thread_cleanup (void)
+{
+ SharedThreadData *data;
+
+ G_LOCK (shared_thread_data);
+ data = shared_thread_data;
+ shared_thread_data = NULL;
+ G_UNLOCK (shared_thread_data);
+
+ _g_dbus_shared_thread_wait_and_free (data);
+}
+
static SharedThreadData *
_g_dbus_shared_thread_ref (void)
{
- static gsize shared_thread_data = 0;
SharedThreadData *ret;
- if (g_once_init_enter (&shared_thread_data))
+ G_LOCK (shared_thread_data);
+ if (!shared_thread_data)
{
SharedThreadData *data;
@@ -299,16 +331,26 @@ _g_dbus_shared_thread_ref (void)
ensure_required_types ();
data = g_new0 (SharedThreadData, 1);
- data->refcount = 0;
+ data->refcount = 1;
data->context = g_main_context_new ();
data->loop = g_main_loop_new (data->context, FALSE);
data->thread = g_thread_new ("gdbus",
gdbus_shared_thread_func,
data);
- /* We can cast between gsize and gpointer safely */
- g_once_init_leave (&shared_thread_data, (gsize) data);
+
+ /*
+ * _g_dbus_shared_thread_wait_and_free() is called by both/either _unref
+ * and _cleanup. In some cases the latter is necessary to break a temporary
+ * ref cycle during shutdown.
+ */
+ g_cleanup_list_push (G_CLEANUP_LOCAL, (GCleanupFunc)_g_dbus_shared_thread_cleanup,
+ NULL, G_CLEANUP_PHASE_EARLY, "_g_dbus_shared_thread_cleanup");
+
+ ret = shared_thread_data = data;
}
+ ret = shared_thread_data;
+ G_UNLOCK (shared_thread_data);
ret = (SharedThreadData*) shared_thread_data;
g_atomic_int_inc (&ret->refcount);
@@ -318,17 +360,16 @@ _g_dbus_shared_thread_ref (void)
static void
_g_dbus_shared_thread_unref (SharedThreadData *data)
{
- /* TODO: actually destroy the shared thread here */
-#if 0
g_assert (data != NULL);
if (g_atomic_int_dec_and_test (&data->refcount))
{
- g_main_loop_quit (data->loop);
- //g_thread_join (data->thread);
- g_main_loop_unref (data->loop);
- g_main_context_unref (data->context);
+ G_LOCK (shared_thread_data);
+ g_assert (shared_thread_data == data);
+ shared_thread_data = NULL;
+ G_UNLOCK (shared_thread_data);
+
+ _g_dbus_shared_thread_wait_and_free (data);
}
-#endif
}
/* ---------------------------------------------------------------------------------------------------- */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]