mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-03 14:42:10 +01:00
GSocket – GSocketSource finalizing not threadsafe on Windows
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
This commit is contained in:
parent
b3b6aab007
commit
ab6b7dbc2e
@ -172,6 +172,7 @@ struct _GSocketPrivate
|
|||||||
int current_errors;
|
int current_errors;
|
||||||
int selected_events;
|
int selected_events;
|
||||||
GList *requested_conditions; /* list of requested GIOCondition * */
|
GList *requested_conditions; /* list of requested GIOCondition * */
|
||||||
|
GMutex win32_source_lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -759,6 +760,7 @@ g_socket_finalize (GObject *object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_assert (socket->priv->requested_conditions == NULL);
|
g_assert (socket->priv->requested_conditions == NULL);
|
||||||
|
g_mutex_clear (&socket->priv->win32_source_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < RECV_ADDR_CACHE_SIZE; i++)
|
for (i = 0; i < RECV_ADDR_CACHE_SIZE; i++)
|
||||||
@ -970,6 +972,7 @@ g_socket_init (GSocket *socket)
|
|||||||
socket->priv->construct_error = NULL;
|
socket->priv->construct_error = NULL;
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
socket->priv->event = WSA_INVALID_EVENT;
|
socket->priv->event = WSA_INVALID_EVENT;
|
||||||
|
g_mutex_init (&socket->priv->win32_source_lock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3074,24 +3077,28 @@ static void
|
|||||||
add_condition_watch (GSocket *socket,
|
add_condition_watch (GSocket *socket,
|
||||||
GIOCondition *condition)
|
GIOCondition *condition)
|
||||||
{
|
{
|
||||||
|
g_mutex_lock (&socket->priv->win32_source_lock);
|
||||||
g_assert (g_list_find (socket->priv->requested_conditions, condition) == NULL);
|
g_assert (g_list_find (socket->priv->requested_conditions, condition) == NULL);
|
||||||
|
|
||||||
socket->priv->requested_conditions =
|
socket->priv->requested_conditions =
|
||||||
g_list_prepend (socket->priv->requested_conditions, condition);
|
g_list_prepend (socket->priv->requested_conditions, condition);
|
||||||
|
|
||||||
update_select_events (socket);
|
update_select_events (socket);
|
||||||
|
g_mutex_unlock (&socket->priv->win32_source_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_condition_watch (GSocket *socket,
|
remove_condition_watch (GSocket *socket,
|
||||||
GIOCondition *condition)
|
GIOCondition *condition)
|
||||||
{
|
{
|
||||||
|
g_mutex_lock (&socket->priv->win32_source_lock);
|
||||||
g_assert (g_list_find (socket->priv->requested_conditions, condition) != NULL);
|
g_assert (g_list_find (socket->priv->requested_conditions, condition) != NULL);
|
||||||
|
|
||||||
socket->priv->requested_conditions =
|
socket->priv->requested_conditions =
|
||||||
g_list_remove (socket->priv->requested_conditions, condition);
|
g_list_remove (socket->priv->requested_conditions, condition);
|
||||||
|
|
||||||
update_select_events (socket);
|
update_select_events (socket);
|
||||||
|
g_mutex_unlock (&socket->priv->win32_source_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GIOCondition
|
static GIOCondition
|
||||||
|
Loading…
x
Reference in New Issue
Block a user