public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: nmontero <nmontero@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/glib2] cve-2026-58016-f44: Add patch to revert gcancellable changes
Date: Tue, 11 Aug 2026 10:38:27 GMT [thread overview]
Message-ID: <178644470740.1.8525398966624693751.rpms-glib2-5f6b1b57bbe1@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/glib2
Branch : cve-2026-58016-f44
Commit : 5f6b1b57bbe1a656bf9e916a489dc27371066004
Author : nmontero <nmontero@redhat.com>
Date : 2025-01-21T17:51:36+01:00
Stats : +705/-0 in 1 file(s)
URL : https://src.fedoraproject.org/rpms/glib2/c/5f6b1b57bbe1a656bf9e916a489dc27371066004?branch=cve-2026-58016-f44
Log:
Add patch to revert gcancellable changes
---
diff --git a/revert-gcancellable-changes.patch b/revert-gcancellable-changes.patch
new file mode 100644
index 0000000..619c3f0
--- /dev/null
+++ b/revert-gcancellable-changes.patch
@@ -0,0 +1,705 @@
+From e239deed94a613c03b8296ae27b5f4142b961eed Mon Sep 17 00:00:00 2001
+From: nmontero <nmontero@redhat.com>
+Date: Tue, 21 Jan 2025 17:32:41 +0100
+Subject: [PATCH 1/4] Revert "gcancellable: Mark assert-only variable as
+ unused"
+
+This reverts commit 6c679fb37a0bfeed7beb42d1b1e3590713eac10c.
+---
+ gio/gcancellable.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gio/gcancellable.c b/gio/gcancellable.c
+index 27dd06370..abf5878ed 100644
+--- a/gio/gcancellable.c
++++ b/gio/gcancellable.c
+@@ -664,7 +664,7 @@ cancellable_source_cancelled (GCancellable *cancellable,
+ {
+ GSource *source = user_data;
+ GCancellableSource *cancellable_source = (GCancellableSource *) source;
+- gboolean callback_was_not_called G_GNUC_UNUSED;
++ gboolean callback_was_not_called;
+
+ g_source_ref (source);
+ g_source_set_ready_time (source, 0);
+--
+2.47.1
+
+
+From 2eec96bcfb654ccb46c2ca0ee51d5c9a972279ac Mon Sep 17 00:00:00 2001
+From: nmontero <nmontero@redhat.com>
+Date: Tue, 21 Jan 2025 17:32:59 +0100
+Subject: [PATCH 2/4] Revert "gcancellable: Reference the object before locking
+ when doing signal emission"
+
+This reverts commit 54d9c26b34d70be9a1e5519bf03d727334c52e0a.
+---
+ gio/gcancellable.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/gio/gcancellable.c b/gio/gcancellable.c
+index abf5878ed..227d56d2e 100644
+--- a/gio/gcancellable.c
++++ b/gio/gcancellable.c
+@@ -495,16 +495,11 @@ g_cancellable_cancel (GCancellable *cancellable)
+
+ priv = cancellable->priv;
+
+- /* We add a reference before locking, to avoid that potential toggle
+- * notifications on the object might happen while we're locked.
+- */
+- g_object_ref (cancellable);
+ g_mutex_lock (&priv->mutex);
+
+ if (!g_atomic_int_compare_and_exchange (&priv->cancelled, FALSE, TRUE))
+ {
+ g_mutex_unlock (&priv->mutex);
+- g_object_unref (cancellable);
+ return;
+ }
+
+@@ -513,6 +508,7 @@ g_cancellable_cancel (GCancellable *cancellable)
+ if (priv->wakeup)
+ GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
+
++ g_object_ref (cancellable);
+ g_signal_emit (cancellable, signals[CANCELLED], 0);
+
+ if (g_atomic_int_dec_and_test (&priv->cancelled_running))
+--
+2.47.1
+
+
+From 6bfdc2dbd4a77ee4ba92154dc20d6908e0a9bd66 Mon Sep 17 00:00:00 2001
+From: nmontero <nmontero@redhat.com>
+Date: Tue, 21 Jan 2025 17:33:16 +0100
+Subject: [PATCH 3/4] Revert "GCancellable: Use per-instance mutex logic
+ instead of global critical sections"
+
+This reverts commit 3a07b2abd4006da33cdfb0916b266a21070a47d6.
+---
+ gio/gcancellable.c | 199 ++++++++++++++++++++++------------------
+ gio/tests/cancellable.c | 10 +-
+ gio/tests/gmenumodel.c | 22 +++--
+ 3 files changed, 129 insertions(+), 102 deletions(-)
+
+diff --git a/gio/gcancellable.c b/gio/gcancellable.c
+index 227d56d2e..c3572910e 100644
+--- a/gio/gcancellable.c
++++ b/gio/gcancellable.c
+@@ -1,7 +1,6 @@
+ /* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+- * Copyright (C) 2022-2024 Canonical, Ltd.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+@@ -19,7 +18,6 @@
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+- * Author: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+ #include "config.h"
+@@ -47,12 +45,14 @@ enum {
+
+ struct _GCancellablePrivate
+ {
+- /* Atomic so that we don't require holding global mutexes for independent ops. */
++ /* Atomic so that g_cancellable_is_cancelled does not require holding the mutex. */
+ gboolean cancelled;
+- int cancelled_running;
++ /* Access to fields below is protected by cancellable_mutex. */
++ guint cancelled_running : 1;
++ guint cancelled_running_waiting : 1;
++ unsigned cancelled_emissions;
++ unsigned cancelled_emissions_waiting : 1;
+
+- /* Access to fields below is protected by cancellable's mutex. */
+- GMutex mutex;
+ guint fd_refcount;
+ GWakeup *wakeup;
+ };
+@@ -62,6 +62,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
+ G_DEFINE_TYPE_WITH_PRIVATE (GCancellable, g_cancellable, G_TYPE_OBJECT)
+
+ static GPrivate current_cancellable;
++static GMutex cancellable_mutex;
+ static GCond cancellable_cond;
+
+ static void
+@@ -69,15 +70,9 @@ g_cancellable_finalize (GObject *object)
+ {
+ GCancellable *cancellable = G_CANCELLABLE (object);
+
+- /* We're at finalization phase, so only one thread can be here.
+- * Thus there's no need to lock. In case something is locking us, then we've
+- * a bug, and g_mutex_clear() will make this clear aborting.
+- */
+ if (cancellable->priv->wakeup)
+ GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup);
+
+- g_mutex_clear (&cancellable->priv->mutex);
+-
+ G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object);
+ }
+
+@@ -159,8 +154,6 @@ static void
+ g_cancellable_init (GCancellable *cancellable)
+ {
+ cancellable->priv = g_cancellable_get_instance_private (cancellable);
+-
+- g_mutex_init (&cancellable->priv->mutex);
+ }
+
+ /**
+@@ -272,17 +265,28 @@ g_cancellable_reset (GCancellable *cancellable)
+
+ g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+
++ g_mutex_lock (&cancellable_mutex);
++
+ priv = cancellable->priv;
+
+- g_mutex_lock (&priv->mutex);
++ while (priv->cancelled_running || priv->cancelled_emissions > 0)
++ {
++ if (priv->cancelled_running)
++ priv->cancelled_running_waiting = TRUE;
++
++ if (priv->cancelled_emissions > 0)
++ priv->cancelled_emissions_waiting = TRUE;
+
+- if (g_atomic_int_compare_and_exchange (&priv->cancelled, TRUE, FALSE))
++ g_cond_wait (&cancellable_cond, &cancellable_mutex);
++ }
++
++ if (g_atomic_int_exchange (&priv->cancelled, FALSE))
+ {
+ if (priv->wakeup)
+ GLIB_PRIVATE_CALL (g_wakeup_acknowledge) (priv->wakeup);
+ }
+
+- g_mutex_unlock (&priv->mutex);
++ g_mutex_unlock (&cancellable_mutex);
+ }
+
+ /**
+@@ -400,29 +404,26 @@ g_cancellable_get_fd (GCancellable *cancellable)
+ gboolean
+ g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
+ {
+- GCancellablePrivate *priv;
+-
+ g_return_val_if_fail (pollfd != NULL, FALSE);
+ if (cancellable == NULL)
+ return FALSE;
+ g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE);
+
+- priv = cancellable->priv;
++ g_mutex_lock (&cancellable_mutex);
+
+- g_mutex_lock (&priv->mutex);
++ cancellable->priv->fd_refcount++;
+
+- if ((priv->fd_refcount++) == 0)
++ if (cancellable->priv->wakeup == NULL)
+ {
+- priv->wakeup = GLIB_PRIVATE_CALL (g_wakeup_new) ();
++ cancellable->priv->wakeup = GLIB_PRIVATE_CALL (g_wakeup_new) ();
+
+- if (g_atomic_int_get (&priv->cancelled))
+- GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
++ if (g_atomic_int_get (&cancellable->priv->cancelled))
++ GLIB_PRIVATE_CALL (g_wakeup_signal) (cancellable->priv->wakeup);
+ }
+
+- g_assert (priv->wakeup);
+- GLIB_PRIVATE_CALL (g_wakeup_get_pollfd) (priv->wakeup, pollfd);
++ GLIB_PRIVATE_CALL (g_wakeup_get_pollfd) (cancellable->priv->wakeup, pollfd);
+
+- g_mutex_unlock (&priv->mutex);
++ g_mutex_unlock (&cancellable_mutex);
+
+ return TRUE;
+ }
+@@ -446,22 +447,26 @@ g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
+ void
+ g_cancellable_release_fd (GCancellable *cancellable)
+ {
++ GCancellablePrivate *priv;
++
+ if (cancellable == NULL)
+ return;
+
+ g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+
+- g_mutex_lock (&cancellable->priv->mutex);
++ priv = cancellable->priv;
+
+- g_assert (cancellable->priv->fd_refcount > 0);
++ g_mutex_lock (&cancellable_mutex);
++ g_assert (priv->fd_refcount > 0);
+
+- if ((cancellable->priv->fd_refcount--) == 1)
++ priv->fd_refcount--;
++ if (priv->fd_refcount == 0)
+ {
+- GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup);
+- cancellable->priv->wakeup = NULL;
++ GLIB_PRIVATE_CALL (g_wakeup_free) (priv->wakeup);
++ priv->wakeup = NULL;
+ }
+
+- g_mutex_unlock (&cancellable->priv->mutex);
++ g_mutex_unlock (&cancellable_mutex);
+ }
+
+ /**
+@@ -490,31 +495,37 @@ g_cancellable_cancel (GCancellable *cancellable)
+ {
+ GCancellablePrivate *priv;
+
+- if (cancellable == NULL || g_atomic_int_get (&cancellable->priv->cancelled))
++ if (cancellable == NULL || g_cancellable_is_cancelled (cancellable))
+ return;
+
+ priv = cancellable->priv;
+
+- g_mutex_lock (&priv->mutex);
++ g_mutex_lock (&cancellable_mutex);
+
+- if (!g_atomic_int_compare_and_exchange (&priv->cancelled, FALSE, TRUE))
++ if (g_atomic_int_exchange (&priv->cancelled, TRUE))
+ {
+- g_mutex_unlock (&priv->mutex);
++ g_mutex_unlock (&cancellable_mutex);
+ return;
+ }
+
+- g_atomic_int_inc (&priv->cancelled_running);
++ priv->cancelled_running = TRUE;
+
+ if (priv->wakeup)
+ GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
+
++ g_mutex_unlock (&cancellable_mutex);
++
+ g_object_ref (cancellable);
+ g_signal_emit (cancellable, signals[CANCELLED], 0);
+
+- if (g_atomic_int_dec_and_test (&priv->cancelled_running))
++ g_mutex_lock (&cancellable_mutex);
++
++ priv->cancelled_running = FALSE;
++ if (priv->cancelled_running_waiting)
+ g_cond_broadcast (&cancellable_cond);
++ priv->cancelled_running_waiting = FALSE;
+
+- g_mutex_unlock (&priv->mutex);
++ g_mutex_unlock (&cancellable_mutex);
+
+ g_object_unref (cancellable);
+ }
+@@ -562,7 +573,7 @@ g_cancellable_connect (GCancellable *cancellable,
+
+ g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), 0);
+
+- g_mutex_lock (&cancellable->priv->mutex);
++ g_mutex_lock (&cancellable_mutex);
+
+ if (g_atomic_int_get (&cancellable->priv->cancelled))
+ {
+@@ -572,10 +583,23 @@ g_cancellable_connect (GCancellable *cancellable,
+ _callback = (void *)callback;
+ id = 0;
+
++ cancellable->priv->cancelled_emissions++;
++
++ g_mutex_unlock (&cancellable_mutex);
++
+ _callback (cancellable, data);
+
+ if (data_destroy_func)
+ data_destroy_func (data);
++
++ g_mutex_lock (&cancellable_mutex);
++
++ if (cancellable->priv->cancelled_emissions_waiting)
++ g_cond_broadcast (&cancellable_cond);
++
++ cancellable->priv->cancelled_emissions--;
++
++ g_mutex_unlock (&cancellable_mutex);
+ }
+ else
+ {
+@@ -583,9 +607,10 @@ g_cancellable_connect (GCancellable *cancellable,
+ callback, data,
+ (GClosureNotify) data_destroy_func,
+ G_CONNECT_DEFAULT);
++
++ g_mutex_unlock (&cancellable_mutex);
+ }
+
+- g_mutex_unlock (&cancellable->priv->mutex);
+
+ return id;
+ }
+@@ -621,26 +646,33 @@ g_cancellable_disconnect (GCancellable *cancellable,
+ if (handler_id == 0 || cancellable == NULL)
+ return;
+
++ g_mutex_lock (&cancellable_mutex);
++
+ priv = cancellable->priv;
+
+- g_mutex_lock (&priv->mutex);
++ while (priv->cancelled_running || priv->cancelled_emissions)
++ {
++ if (priv->cancelled_running)
++ priv->cancelled_running_waiting = TRUE;
+
+- while (g_atomic_int_get (&priv->cancelled_running) != 0)
+- g_cond_wait (&cancellable_cond, &priv->mutex);
++ if (priv->cancelled_emissions)
++ priv->cancelled_emissions_waiting = TRUE;
+
+- g_mutex_unlock (&priv->mutex);
++ g_cond_wait (&cancellable_cond, &cancellable_mutex);
++ }
+
+ g_signal_handler_disconnect (cancellable, handler_id);
++
++ g_mutex_unlock (&cancellable_mutex);
+ }
+
+ typedef struct {
+ GSource source;
+
+- /* Atomic: */
+ GCancellable *cancellable;
+ gulong cancelled_handler;
+- /* Atomic: */
+- gboolean cancelled_callback_called;
++ /* Protected by cancellable_mutex: */
++ gboolean resurrected_during_cancellation;
+ } GCancellableSource;
+
+ /*
+@@ -660,35 +692,27 @@ cancellable_source_cancelled (GCancellable *cancellable,
+ {
+ GSource *source = user_data;
+ GCancellableSource *cancellable_source = (GCancellableSource *) source;
+- gboolean callback_was_not_called;
+
+- g_source_ref (source);
+- g_source_set_ready_time (source, 0);
++ g_mutex_lock (&cancellable_mutex);
+
+- callback_was_not_called = g_atomic_int_compare_and_exchange (
+- &cancellable_source->cancelled_callback_called, FALSE, TRUE);
+- g_assert (callback_was_not_called);
++ /* Drop the reference added in cancellable_source_dispose(); see the comment there.
++ * The reference must be dropped after unlocking @cancellable_mutex since
++ * it could be the final reference, and the dispose function takes
++ * @cancellable_mutex. */
++ if (cancellable_source->resurrected_during_cancellation)
++ {
++ cancellable_source->resurrected_during_cancellation = FALSE;
++ g_mutex_unlock (&cancellable_mutex);
++ g_source_unref (source);
++ return;
++ }
+
++ g_source_ref (source);
++ g_mutex_unlock (&cancellable_mutex);
++ g_source_set_ready_time (source, 0);
+ g_source_unref (source);
+ }
+
+-static gboolean
+-cancellable_source_prepare (GSource *source,
+- gint *timeout)
+-{
+- GCancellableSource *cancellable_source = (GCancellableSource *) source;
+- GCancellable *cancellable;
+-
+- if (timeout)
+- *timeout = -1;
+-
+- cancellable = g_atomic_pointer_get (&cancellable_source->cancellable);
+- if (cancellable && !g_atomic_int_get (&cancellable->priv->cancelled_running))
+- g_atomic_int_set (&cancellable_source->cancelled_callback_called, FALSE);
+-
+- return FALSE;
+-}
+-
+ static gboolean
+ cancellable_source_dispatch (GSource *source,
+ GSourceFunc callback,
+@@ -705,13 +729,12 @@ static void
+ cancellable_source_dispose (GSource *source)
+ {
+ GCancellableSource *cancellable_source = (GCancellableSource *)source;
+- GCancellable *cancellable;
+
+- cancellable = g_atomic_pointer_exchange (&cancellable_source->cancellable, NULL);
++ g_mutex_lock (&cancellable_mutex);
+
+- if (cancellable)
++ if (cancellable_source->cancellable)
+ {
+- if (g_atomic_int_get (&cancellable->priv->cancelled_running))
++ if (cancellable_source->cancellable->priv->cancelled_running)
+ {
+ /* There can be a race here: if thread A has called
+ * g_cancellable_cancel() and has got as far as committing to call
+@@ -723,21 +746,21 @@ cancellable_source_dispose (GSource *source)
+ * will then be left in a state where it’s committed to using a
+ * dangling GCancellableSource pointer.
+ *
+- * Eliminate that race by waiting to ensure that our cancelled
+- * callback has been called, keeping a temporary ref, so that
+- * there's no risk that we're unreffing something that is still
+- * going to be used.
++ * Eliminate that race by resurrecting the #GSource temporarily, and
++ * then dropping that reference in cancellable_source_cancelled(),
++ * which should be guaranteed to fire because we’re inside a
++ * @cancelled_running block.
+ */
+-
+ g_source_ref (source);
+- while (!g_atomic_int_get (&cancellable_source->cancelled_callback_called))
+- ;
+- g_source_unref (source);
++ cancellable_source->resurrected_during_cancellation = TRUE;
+ }
+
+- g_clear_signal_handler (&cancellable_source->cancelled_handler, cancellable);
+- g_object_unref (cancellable);
++ g_clear_signal_handler (&cancellable_source->cancelled_handler,
++ cancellable_source->cancellable);
++ g_clear_object (&cancellable_source->cancellable);
+ }
++
++ g_mutex_unlock (&cancellable_mutex);
+ }
+
+ static gboolean
+@@ -766,7 +789,7 @@ cancellable_source_closure_callback (GCancellable *cancellable,
+
+ static GSourceFuncs cancellable_source_funcs =
+ {
+- cancellable_source_prepare,
++ NULL,
+ NULL,
+ cancellable_source_dispatch,
+ NULL,
+diff --git a/gio/tests/cancellable.c b/gio/tests/cancellable.c
+index fa84e2e2c..6f25d63d9 100644
+--- a/gio/tests/cancellable.c
++++ b/gio/tests/cancellable.c
+@@ -261,6 +261,11 @@ threaded_dispose_thread_cb (gpointer user_data)
+ static void
+ test_cancellable_source_threaded_dispose (void)
+ {
++#ifdef _GLIB_ADDRESS_SANITIZER
++ g_test_incomplete ("FIXME: Leaks lots of GCancellableSource objects, see glib#2309");
++ (void) cancelled_cb;
++ (void) threaded_dispose_thread_cb;
++#else
+ ThreadedDisposeData data;
+ GThread *thread = NULL;
+ guint i;
+@@ -270,10 +275,6 @@ test_cancellable_source_threaded_dispose (void)
+ "(in one thread) and cancelling the GCancellable it refers "
+ "to (in another thread)");
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1841");
+-#ifdef _GLIB_ADDRESS_SANITIZER
+- g_test_message ("We also ensure that no GCancellableSource are leaked");
+- g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/2309");
+-#endif
+
+ /* Create a new thread and wait until it’s ready to execute. Each iteration of
+ * the test will pass it a new #GCancellableSource. */
+@@ -334,6 +335,7 @@ test_cancellable_source_threaded_dispose (void)
+ g_cond_clear (&data.cond);
+
+ g_ptr_array_unref (cancellables_pending_unref);
++#endif
+ }
+
+ static void
+diff --git a/gio/tests/gmenumodel.c b/gio/tests/gmenumodel.c
+index 75f5d85f9..22d1b4d61 100644
+--- a/gio/tests/gmenumodel.c
++++ b/gio/tests/gmenumodel.c
+@@ -1007,16 +1007,17 @@ test_dbus_roundtrip (void)
+ static void
+ test_dbus_peer_roundtrip (void)
+ {
+- 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
++ g_test_incomplete ("FIXME: Leaks a GCancellableSource, see glib#2313");
++ (void) peer_connection_up;
++ (void) peer_connection_down;
++#else
++ PeerConnection peer;
+
+ peer_connection_up (&peer);
+ do_roundtrip (peer.server_connection, peer.client_connection);
+ peer_connection_down (&peer);
++#endif
+ }
+
+ static gint items_changed_count;
+@@ -1145,16 +1146,17 @@ test_dbus_subscriptions (void)
+ static void
+ test_dbus_peer_subscriptions (void)
+ {
+- 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
++ g_test_incomplete ("FIXME: Leaks a GCancellableSource, see glib#2313");
++ (void) peer_connection_up;
++ (void) peer_connection_down;
++#else
++ PeerConnection peer;
+
+ peer_connection_up (&peer);
+ do_subscriptions (peer.server_connection, peer.client_connection);
+ peer_connection_down (&peer);
++#endif
+ }
+
+ static void
+--
+2.47.1
+
+
+From df7d92ed028c888de57aaaa2b97580084989e89b Mon Sep 17 00:00:00 2001
+From: nmontero <nmontero@redhat.com>
+Date: Tue, 21 Jan 2025 17:33:25 +0100
+Subject: [PATCH 4/4] Revert "gio/tests: Ensure that a GCancellableSource can
+ be used muliple times"
+
+This reverts commit 0a8cb10f224ff2dfed14f6500e77cee68ae7d4c4.
+---
+ gio/gcancellable.c | 8 ++----
+ gio/tests/cancellable.c | 64 -----------------------------------------
+ 2 files changed, 3 insertions(+), 69 deletions(-)
+
+diff --git a/gio/gcancellable.c b/gio/gcancellable.c
+index c3572910e..41ffab322 100644
+--- a/gio/gcancellable.c
++++ b/gio/gcancellable.c
+@@ -541,11 +541,9 @@ g_cancellable_cancel (GCancellable *cancellable)
+ * signal. Also handles the race condition that may happen
+ * if the cancellable is cancelled right before connecting.
+ *
+- * @callback is called exactly once each time @cancellable is cancelled,
+- * either directly at the time of the connect if @cancellable is already
+- * cancelled, or when @cancellable is cancelled in some thread.
+- * In case the cancellable is reset via [method@Gio.Cancellable.reset]
+- * then the callback can be called again if the @cancellable is cancelled.
++ * @callback is called at most once, either directly at the
++ * time of the connect if @cancellable is already cancelled,
++ * or when @cancellable is cancelled in some thread.
+ *
+ * @data_destroy_func will be called when the handler is
+ * disconnected, or immediately if the cancellable is already
+diff --git a/gio/tests/cancellable.c b/gio/tests/cancellable.c
+index 6f25d63d9..3f6854462 100644
+--- a/gio/tests/cancellable.c
++++ b/gio/tests/cancellable.c
+@@ -810,69 +810,6 @@ test_cancellable_cancel_reset_connect_races (void)
+ g_object_unref (cancellable);
+ }
+
+-static gboolean
+-source_cancelled_counter_cb (GCancellable *cancellable,
+- gpointer user_data)
+-{
+- guint *n_calls = user_data;
+-
+- *n_calls = *n_calls + 1;
+-
+- return G_SOURCE_CONTINUE;
+-}
+-
+-static void
+-do_nothing (G_GNUC_UNUSED void *user_data)
+-{
+- /* An empty timeout/idle once callback function */
+-}
+-
+-static void
+-test_cancellable_source_can_be_fired_multiple_times (void)
+-{
+- GCancellable *cancellable;
+- GSource *source;
+- guint n_calls = 0;
+-
+- g_test_summary ("Test a cancellable source callback can be called multiple times");
+- g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/774");
+-
+- cancellable = g_cancellable_new ();
+- source = g_cancellable_source_new (cancellable);
+-
+- g_source_set_callback (source, G_SOURCE_FUNC (source_cancelled_counter_cb),
+- &n_calls, NULL);
+- g_source_attach (source, NULL);
+-
+- g_cancellable_cancel (cancellable);
+- g_assert_cmpuint (n_calls, ==, 0);
+-
+- while (g_main_context_pending (NULL))
+- g_main_context_iteration (NULL, TRUE);
+-
+- g_assert_cmpuint (n_calls, ==, 1);
+-
+- g_cancellable_cancel (cancellable);
+-
+- g_timeout_add_once (100, do_nothing, NULL);
+- while (g_main_context_pending (NULL))
+- g_main_context_iteration (NULL, TRUE);
+-
+- g_assert_cmpuint (n_calls, ==, 1);
+-
+- g_cancellable_reset (cancellable);
+- g_cancellable_cancel (cancellable);
+- g_assert_cmpuint (n_calls, ==, 1);
+-
+- while (g_main_context_pending (NULL))
+- g_main_context_iteration (NULL, TRUE);
+-
+- g_assert_cmpuint (n_calls, ==, 2);
+-
+- g_source_unref (source);
+- g_object_unref (cancellable);
+-}
+-
+ int
+ main (int argc, char *argv[])
+ {
+@@ -888,7 +825,6 @@ main (int argc, char *argv[])
+ g_test_add_func ("/cancellable/cancel-reset-races", test_cancellable_cancel_reset_races);
+ g_test_add_func ("/cancellable/cancel-reset-connect-races", test_cancellable_cancel_reset_connect_races);
+ g_test_add_func ("/cancellable-source/threaded-dispose", test_cancellable_source_threaded_dispose);
+- g_test_add_func ("/cancellable-source/can-be-fired-multiple-times", test_cancellable_source_can_be_fired_multiple_times);
+
+ return g_test_run ();
+ }
+--
+2.47.1
+
reply other threads:[~2026-08-11 10:38 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178644470740.1.8525398966624693751.rpms-glib2-5f6b1b57bbe1@fedoraproject.org \
--to=nmontero@redhat.com \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox