From ab6b7dbc2efc506e43616941ac70f14fc20de574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 28 Jul 2013 16:43:44 +0200 Subject: [PATCH] =?UTF-8?q?GSocket=20=E2=80=93=20GSocketSource=20finalizin?= =?UTF-8?q?g=20not=20threadsafe=20on=20Windows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The requested_conditions list access is not threadsafe. When passing the socket ownership from a GSource callback to another thread, which also creates a GSocketSource for the socket, it can happen that the original GSocketSource is finalized at the same time as the new one is created. This would cause inconsistencies in the requested_conditions list and can cause assertions or completely undefined behaviour. https://bugzilla.gnome.org/show_bug.cgi?id=705027 --- gio/gsocket.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gio/gsocket.c b/gio/gsocket.c index b60617146..7f99a60f6 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -172,6 +172,7 @@ struct _GSocketPrivate int current_errors; int selected_events; GList *requested_conditions; /* list of requested GIOCondition * */ + GMutex win32_source_lock; #endif struct { @@ -759,6 +760,7 @@ g_socket_finalize (GObject *object) } g_assert (socket->priv->requested_conditions == NULL); + g_mutex_clear (&socket->priv->win32_source_lock); #endif for (i = 0; i < RECV_ADDR_CACHE_SIZE; i++) @@ -970,6 +972,7 @@ g_socket_init (GSocket *socket) socket->priv->construct_error = NULL; #ifdef G_OS_WIN32 socket->priv->event = WSA_INVALID_EVENT; + g_mutex_init (&socket->priv->win32_source_lock); #endif } @@ -3074,24 +3077,28 @@ static void add_condition_watch (GSocket *socket, GIOCondition *condition) { + g_mutex_lock (&socket->priv->win32_source_lock); g_assert (g_list_find (socket->priv->requested_conditions, condition) == NULL); socket->priv->requested_conditions = g_list_prepend (socket->priv->requested_conditions, condition); update_select_events (socket); + g_mutex_unlock (&socket->priv->win32_source_lock); } static void remove_condition_watch (GSocket *socket, GIOCondition *condition) { + g_mutex_lock (&socket->priv->win32_source_lock); g_assert (g_list_find (socket->priv->requested_conditions, condition) != NULL); socket->priv->requested_conditions = g_list_remove (socket->priv->requested_conditions, condition); update_select_events (socket); + g_mutex_unlock (&socket->priv->win32_source_lock); } static GIOCondition