summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoss Lagerwall <rosslagerwall@gmail.com>2014-10-28 21:16:50 +0000
committerDan Winship <danw@gnome.org>2014-11-23 12:02:38 -0500
commit9a6e01ea5bde908e2bcce4dc66d89483e84fd837 (patch)
tree02d4a9584b4a14403f97fdffbe3c75f23657765d
parent91802bbf2bfd336aec640c9412f955b1df8f80ae (diff)
downloadglib-9a6e01ea5bde908e2bcce4dc66d89483e84fd837.tar.gz
glib-9a6e01ea5bde908e2bcce4dc66d89483e84fd837.tar.bz2
glib-9a6e01ea5bde908e2bcce4dc66d89483e84fd837.zip
gio: Prevent hang when finalizing GThreadedSocketService
If all users of a GThreadedSocketService release their references to the service while a connection thread is running, the thread function will release the last reference to the service which causes the finalize to deadlock waiting for all threads to finish (because it's called from the thread function). To fix this, don't wait for all threads to finish in the service's finalize method. Since the threads hold a reference to the service, finalize should only be called when all threads are finished running (or have unrefed the service and are about to finish). https://bugzilla.gnome.org/show_bug.cgi?id=712570
-rw-r--r--gio/gthreadedsocketservice.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/gio/gthreadedsocketservice.c b/gio/gthreadedsocketservice.c
index f18238c17..ab4bd0050 100644
--- a/gio/gthreadedsocketservice.c
+++ b/gio/gthreadedsocketservice.c
@@ -72,7 +72,6 @@ G_LOCK_DEFINE_STATIC(job_count);
typedef struct
{
- GThreadedSocketService *service;
GSocketConnection *connection;
GObject *source_object;
} GThreadedSocketServiceData;
@@ -85,10 +84,9 @@ g_threaded_socket_service_func (gpointer _data,
GThreadedSocketServiceData *data = _data;
gboolean result;
- g_signal_emit (data->service, g_threaded_socket_service_run_signal,
+ g_signal_emit (threaded, g_threaded_socket_service_run_signal,
0, data->connection, data->source_object, &result);
- g_object_unref (data->service);
g_object_unref (data->connection);
if (data->source_object)
g_object_unref (data->source_object);
@@ -98,6 +96,8 @@ g_threaded_socket_service_func (gpointer _data,
if (threaded->priv->job_count-- == threaded->priv->max_threads)
g_socket_service_start (G_SOCKET_SERVICE (threaded));
G_UNLOCK (job_count);
+
+ g_object_unref (threaded);
}
static gboolean
@@ -111,7 +111,10 @@ g_threaded_socket_service_incoming (GSocketService *service,
threaded = G_THREADED_SOCKET_SERVICE (service);
data = g_slice_new (GThreadedSocketServiceData);
- data->service = g_object_ref (service);
+
+ /* Ref the socket service for the thread */
+ g_object_ref (service);
+
data->connection = g_object_ref (connection);
if (source_object)
data->source_object = g_object_ref (source_object);
@@ -156,7 +159,7 @@ g_threaded_socket_service_finalize (GObject *object)
{
GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object);
- g_thread_pool_free (service->priv->thread_pool, FALSE, TRUE);
+ g_thread_pool_free (service->priv->thread_pool, FALSE, FALSE);
G_OBJECT_CLASS (g_threaded_socket_service_parent_class)
->finalize (object);