gthreadedsocketservice: Move obj reference to per-job data

Rather than keeping a reference to the GThreadedSocketService as the
user_data for every thread pool job, add it to a member of the per-job
data struct (GThreadedSocketServiceData). This should make no
difference overall, as it’s just moving the refcounting around, but it
does seem to fix an occasional double-unref crash on shutdown where the
GThreadedSocketService is unreffed during finalisation.

In any case, it makes the object ownership clearer.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
Philip Withnall 2019-04-12 15:22:19 +01:00
parent 63823ae628
commit 035c5d03f1

View File

@ -71,32 +71,33 @@ G_LOCK_DEFINE_STATIC(job_count);
typedef struct typedef struct
{ {
GSocketConnection *connection; GThreadedSocketService *service; /* (owned) */
GObject *source_object; GSocketConnection *connection; /* (owned) */
GObject *source_object; /* (owned) (nullable) */
} GThreadedSocketServiceData; } GThreadedSocketServiceData;
static void static void
g_threaded_socket_service_data_free (GThreadedSocketServiceData *data) g_threaded_socket_service_data_free (GThreadedSocketServiceData *data)
{ {
g_clear_object (&data->service);
g_clear_object (&data->connection); g_clear_object (&data->connection);
g_clear_object (&data->source_object); g_clear_object (&data->source_object);
g_slice_free (GThreadedSocketServiceData, data); g_slice_free (GThreadedSocketServiceData, data);
} }
static void static void
g_threaded_socket_service_func (gpointer _data, g_threaded_socket_service_func (gpointer job_data,
gpointer user_data) gpointer user_data)
{ {
GThreadedSocketService *threaded = user_data; GThreadedSocketServiceData *data = job_data;
GThreadedSocketServiceData *data = _data;
gboolean result; gboolean result;
g_signal_emit (threaded, g_threaded_socket_service_run_signal, g_signal_emit (data->service, g_threaded_socket_service_run_signal,
0, data->connection, data->source_object, &result); 0, data->connection, data->source_object, &result);
G_LOCK (job_count); G_LOCK (job_count);
if (threaded->priv->job_count-- == threaded->priv->max_threads) if (data->service->priv->job_count-- == data->service->priv->max_threads)
g_socket_service_start (G_SOCKET_SERVICE (threaded)); g_socket_service_start (G_SOCKET_SERVICE (data->service));
G_UNLOCK (job_count); G_UNLOCK (job_count);
g_threaded_socket_service_data_free (data); g_threaded_socket_service_data_free (data);
@ -112,16 +113,10 @@ g_threaded_socket_service_incoming (GSocketService *service,
threaded = G_THREADED_SOCKET_SERVICE (service); threaded = G_THREADED_SOCKET_SERVICE (service);
data = g_slice_new (GThreadedSocketServiceData); data = g_slice_new0 (GThreadedSocketServiceData);
data->service = g_object_ref (threaded);
/* Ref the socket service for the thread */
g_object_ref (service);
data->connection = g_object_ref (connection); data->connection = g_object_ref (connection);
if (source_object) data->source_object = (source_object != NULL) ? g_object_ref (source_object) : NULL;
data->source_object = g_object_ref (source_object);
else
data->source_object = NULL;
G_LOCK (job_count); G_LOCK (job_count);
if (++threaded->priv->job_count == threaded->priv->max_threads) if (++threaded->priv->job_count == threaded->priv->max_threads)
@ -149,7 +144,7 @@ g_threaded_socket_service_constructed (GObject *object)
service->priv->thread_pool = service->priv->thread_pool =
g_thread_pool_new (g_threaded_socket_service_func, g_thread_pool_new (g_threaded_socket_service_func,
service, NULL,
service->priv->max_threads, service->priv->max_threads,
FALSE, FALSE,
NULL); NULL);
@ -161,6 +156,8 @@ g_threaded_socket_service_finalize (GObject *object)
{ {
GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object); GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object);
/* All jobs in the pool hold a reference to this #GThreadedSocketService, so
* this should only be called once the pool is empty: */
g_thread_pool_free (service->priv->thread_pool, FALSE, FALSE); g_thread_pool_free (service->priv->thread_pool, FALSE, FALSE);
G_OBJECT_CLASS (g_threaded_socket_service_parent_class) G_OBJECT_CLASS (g_threaded_socket_service_parent_class)