GCancellable: Use per-instance mutex logic instead of global critical sections

GCancellable is meant to be used in multi-thread operations but all the
cancellable instances were sharing a single mutex to synchronize them
which can be less optimal when many instances are in place.
Especially when we're doing a lock/unlock dances that may leave another
thread to take the control of a critical section in an unexpected way.

This in fact was leading to some races in GCancellableSources causing
leaks because we were assuming that the "cancelled" callback was always
called before our dispose implementation.

As per this, use per-instance mutexes.

The lock is also now used only to protect the calls that may interact
with cancelled state or that depends on that, as per this we can just
reduce it to the cancel and reset case, other than to the connect one to
prevent the race that we could have when connecting to a cancellable
that is reset from another thread.

We don't really need to release the locks during callbacks now as they
are per instance, and there's really no function that we allowed to call
during a ::cancelled signal callback that may require an unlocked state.
This could been done in case with a recursive lock, that is easy enough
to implement but not really needed for this case.

Fixes: #2309, #2313
This commit is contained in:
Marco Trevisan (Treviño)
2022-06-21 05:58:00 +02:00
parent 0a8cb10f22
commit 3a07b2abd4
3 changed files with 102 additions and 129 deletions

View File

@@ -1007,17 +1007,16 @@ test_dbus_roundtrip (void)
static void
test_dbus_peer_roundtrip (void)
{
#ifdef _GLIB_ADDRESS_SANITIZER
g_test_incomplete ("FIXME: Leaks a GCancellableSource, see glib#2313");
(void) peer_connection_up;
(void) peer_connection_down;
#else
PeerConnection peer;
#ifdef _GLIB_ADDRESS_SANITIZER
g_test_message ("Ensure that no GCancellableSource are leaked");
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/2313");
#endif
peer_connection_up (&peer);
do_roundtrip (peer.server_connection, peer.client_connection);
peer_connection_down (&peer);
#endif
}
static gint items_changed_count;
@@ -1146,17 +1145,16 @@ test_dbus_subscriptions (void)
static void
test_dbus_peer_subscriptions (void)
{
#ifdef _GLIB_ADDRESS_SANITIZER
g_test_incomplete ("FIXME: Leaks a GCancellableSource, see glib#2313");
(void) peer_connection_up;
(void) peer_connection_down;
#else
PeerConnection peer;
#ifdef _GLIB_ADDRESS_SANITIZER
g_test_message ("Ensure that no GCancellableSource are leaked");
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/2313");
#endif
peer_connection_up (&peer);
do_subscriptions (peer.server_connection, peer.client_connection);
peer_connection_down (&peer);
#endif
}
static void