From 2f3518c80dc08aeddfd65273b79d39b325664e3f Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Fri, 10 Jan 2020 15:04:44 -0800 Subject: [PATCH] gtkmain: be deterministic in source removal Fixes gtk_main_sync() to only remove a source if it has not already executed (and been removed). The previous code was using gtk_main_quit() directly which would be non-determinstic based on the previous value in the return register. --- gtk/gtkmain.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 93fea8540a..37ee557c48 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1044,6 +1044,7 @@ gtk_main (void) typedef struct { GMainLoop *store_loop; guint n_clipboards; + guint timeout_id; } ClipboardStore; static void @@ -1071,13 +1072,20 @@ clipboard_store_finished (GObject *source, g_main_loop_quit (store->store_loop); } +static gboolean +sync_timed_out_cb (ClipboardStore *store) +{ + store->timeout_id = 0; + g_main_loop_quit (store->store_loop); + return G_SOURCE_REMOVE; +} + void gtk_main_sync (void) { ClipboardStore store = { NULL, }; GSList *displays, *l; GCancellable *cancel; - guint store_timeout; /* Try storing all clipboard data we have */ displays = gdk_display_manager_list_displays (gdk_display_manager_get ()); @@ -1101,17 +1109,16 @@ gtk_main_sync (void) g_slist_free (displays); store.store_loop = g_main_loop_new (NULL, TRUE); - store_timeout = g_timeout_add_seconds (10, (GSourceFunc) g_main_loop_quit, store.store_loop); - g_source_set_name_by_id (store_timeout, "[gtk] gtk_main_sync clipboard store timeout"); + store.timeout_id = g_timeout_add_seconds (10, (GSourceFunc) sync_timed_out_cb, &store); + g_source_set_name_by_id (store.timeout_id, "[gtk] gtk_main_sync clipboard store timeout"); if (g_main_loop_is_running (store.store_loop)) g_main_loop_run (store.store_loop); g_cancellable_cancel (cancel); g_object_unref (cancel); - g_source_remove (store_timeout); - g_main_loop_unref (store.store_loop); - store.store_loop = NULL; + g_clear_handle_id (&store.timeout_id, g_source_remove); + g_clear_pointer (&store.store_loop, g_main_loop_unref); /* Synchronize the recent manager singleton */ _gtk_recent_manager_sync (); -- 2.30.2