Blame SOURCES/0001-open-document-selector-Properly-remove-idle.patch

3fc286
From 8447b9f9369ce850f1888b4bd8d03540de88cab0 Mon Sep 17 00:00:00 2001
3fc286
From: Andrea Azzarone <andrea.azzarone@canonical.com>
3fc286
Date: Tue, 2 Apr 2019 17:33:12 +0100
3fc286
Subject: [PATCH] open-document-selector: Properly remove idle
3fc286
3fc286
It's not possible to use g_idle_remove_by_data when the idle was added with
3fc286
gdk_threads_add_idle_full. gdk_threads_add_idle_full uses g_idle_add_full
3fc286
internally but it creates a temporary data strucuture. The address of this
3fc286
temporary data structure should be passed to g_idle_remove_by_data. For obvious
3fc286
reasons we cannot do that, so let's use g_source_remove.
3fc286
3fc286
Failing to remove the idle when the open document selector is disposed could
3fc286
result in a crash because the idle function (real_populate_liststore) would
3fc286
access invalid memory.
3fc286
3fc286
Also remove populate_scheduled because it's not needed for two reasons:
3fc286
1. populate_liststore and real_populate_liststore always run in the same thread
3fc286
2. if populate_liststore is called before real_populate_liststore is run, there
3fc286
   is no need to schedule two calls two real_populate_liststore.
3fc286
3fc286
Close: https://bugs.launchpad.net/bugs/1646762
3fc286
---
3fc286
 gedit/gedit-open-document-selector.c | 36 ++++++++++------------------
3fc286
 1 file changed, 12 insertions(+), 24 deletions(-)
3fc286
3fc286
diff --git a/gedit/gedit-open-document-selector.c b/gedit/gedit-open-document-selector.c
3fc286
index 5389ef0bd..b3c1ed503 100644
3fc286
--- a/gedit/gedit-open-document-selector.c
3fc286
+++ b/gedit/gedit-open-document-selector.c
3fc286
@@ -24,77 +24,76 @@
3fc286
 
3fc286
 #include <time.h>
3fc286
 
3fc286
 #include <glib.h>
3fc286
 #include <glib/gi18n.h>
3fc286
 #include <gtk/gtk.h>
3fc286
 
3fc286
 #include <glib/gstdio.h>
3fc286
 #include <gio/gio.h>
3fc286
 
3fc286
 #include "gedit-recent.h"
3fc286
 #include "gedit-utils.h"
3fc286
 #include "gedit-window.h"
3fc286
 #include "gedit-debug.h"
3fc286
 
3fc286
 struct _GeditOpenDocumentSelector
3fc286
 {
3fc286
 	GtkBox parent_instance;
3fc286
 
3fc286
 	GeditWindow *window;
3fc286
 	GtkWidget *search_entry;
3fc286
 
3fc286
 	GtkWidget *open_button;
3fc286
 	GtkWidget *treeview;
3fc286
 	GtkListStore *liststore;
3fc286
 	GtkCellRenderer *name_renderer;
3fc286
 	GtkCellRenderer *path_renderer;
3fc286
 	GtkWidget *placeholder_box;
3fc286
 	GtkWidget *scrolled_window;
3fc286
 
3fc286
+	guint populate_listbox_id;
3fc286
+
3fc286
 	GdkRGBA name_label_color;
3fc286
 	PangoFontDescription *name_font;
3fc286
 	GdkRGBA path_label_color;
3fc286
 	PangoFontDescription *path_font;
3fc286
 
3fc286
 	GeditOpenDocumentSelectorStore *selector_store;
3fc286
 	GList *recent_items;
3fc286
 	GList *home_dir_items;
3fc286
 	GList *desktop_dir_items;
3fc286
 	GList *local_bookmarks_dir_items;
3fc286
 	GList *file_browser_root_items;
3fc286
 	GList *active_doc_dir_items;
3fc286
 	GList *current_docs_items;
3fc286
 	GList *all_items;
3fc286
-
3fc286
-	guint populate_liststore_is_idle : 1;
3fc286
-	guint populate_scheduled : 1;
3fc286
 };
3fc286
 
3fc286
 typedef enum
3fc286
 {
3fc286
 	SELECTOR_TAG_NONE,
3fc286
 	SELECTOR_TAG_MATCH
3fc286
 } SelectorTag;
3fc286
 
3fc286
 enum
3fc286
 {
3fc286
 	NAME_COLUMN,
3fc286
 	PATH_COLUMN,
3fc286
 	URI_COLUMN,
3fc286
 	N_COLUMNS
3fc286
 };
3fc286
 
3fc286
 enum
3fc286
 {
3fc286
 	PROP_0,
3fc286
 	PROP_WINDOW,
3fc286
 	LAST_PROP
3fc286
 };
3fc286
 
3fc286
 static GParamSpec *properties[LAST_PROP];
3fc286
 
3fc286
 enum
3fc286
 {
3fc286
 	SELECTOR_FILE_ACTIVATED,
3fc286
 	LAST_SIGNAL
3fc286
 };
3fc286
@@ -483,61 +482,60 @@ fileitem_list_remove_duplicates (GList *items)
3fc286
 		GList *l1;
3fc286
 
3fc286
 		if ((l1 = l->next) == NULL)
3fc286
 		{
3fc286
 			break;
3fc286
 		}
3fc286
 
3fc286
 		l_uri = ((FileItem *)l->data)->uri;
3fc286
 		l1_uri = ((FileItem *)l1->data)->uri;
3fc286
 		if (g_strcmp0 (l_uri, l1_uri) == 0)
3fc286
 		{
3fc286
 			gedit_open_document_selector_free_fileitem_item ((FileItem *)l1->data);
3fc286
 			dummy_ptr = g_list_delete_link (items, l1);
3fc286
 		}
3fc286
 		else
3fc286
 		{
3fc286
 			l = l->next;
3fc286
 		}
3fc286
 	}
3fc286
 }
3fc286
 
3fc286
 static gboolean
3fc286
 real_populate_liststore (gpointer data)
3fc286
 {
3fc286
 	GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (data);
3fc286
 	GeditOpenDocumentSelectorStore *selector_store;
3fc286
 	GList *l;
3fc286
 	GList *filter_items = NULL;
3fc286
 	gchar *filter;
3fc286
 	GRegex *filter_regex = NULL;
3fc286
-	selector->populate_liststore_is_idle = FALSE;
3fc286
 
3fc286
 	DEBUG_SELECTOR_TIMER_DECL
3fc286
 	DEBUG_SELECTOR_TIMER_NEW
3fc286
 
3fc286
 	gtk_list_store_clear (selector->liststore);
3fc286
 
3fc286
 	selector_store = selector->selector_store;
3fc286
 	filter = gedit_open_document_selector_store_get_filter (selector_store);
3fc286
 	if (filter && *filter != '\0')
3fc286
 	{
3fc286
 		DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: all lists\n", selector););
3fc286
 
3fc286
 		filter_items = fileitem_list_filter (selector->all_items, (const gchar *)filter);
3fc286
 		filter_items = g_list_sort_with_data (filter_items, (GCompareDataFunc)sort_items_by_mru, NULL);
3fc286
 		fileitem_list_remove_duplicates (filter_items);
3fc286
 
3fc286
 		filter_regex = g_regex_new (filter, G_REGEX_CASELESS, 0, NULL);
3fc286
 	}
3fc286
 	else
3fc286
 	{
3fc286
 		gint recent_limit;
3fc286
 		GList *recent_items;
3fc286
 
3fc286
 		DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: recent files list\n", selector););
3fc286
 
3fc286
 		recent_limit = gedit_open_document_selector_store_get_recent_limit (selector_store);
3fc286
 
3fc286
 		if (recent_limit > 0 )
3fc286
 		{
3fc286
 			recent_items = fileitem_list_filter (selector->recent_items, NULL);
3fc286
@@ -551,87 +549,79 @@ real_populate_liststore (gpointer data)
3fc286
 	}
3fc286
 
3fc286
 	g_free (filter);
3fc286
 
3fc286
 	DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: length:%i\n",
3fc286
 	                         selector, g_list_length (filter_items)););
3fc286
 
3fc286
 	/* Show the placeholder if no results, show the treeview otherwise */
3fc286
 	gtk_widget_set_visible (selector->scrolled_window, (filter_items != NULL));
3fc286
 	gtk_widget_set_visible (selector->placeholder_box, (filter_items == NULL));
3fc286
 
3fc286
 	for (l = filter_items; l != NULL; l = l->next)
3fc286
 	{
3fc286
 		FileItem *item;
3fc286
 
3fc286
 		item = l->data;
3fc286
 		create_row (selector, (const FileItem *)item, filter_regex);
3fc286
 	}
3fc286
 
3fc286
 	if (filter_regex)
3fc286
 	{
3fc286
 		g_regex_unref (filter_regex);
3fc286
 	}
3fc286
 
3fc286
 	gedit_open_document_selector_free_file_items_list (filter_items);
3fc286
 
3fc286
 	DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: time:%lf\n\n",
3fc286
 	                          selector, DEBUG_SELECTOR_TIMER_GET););
3fc286
 	DEBUG_SELECTOR_TIMER_DESTROY
3fc286
 
3fc286
-	if (selector->populate_scheduled)
3fc286
-	{
3fc286
-		selector->populate_scheduled = FALSE;
3fc286
-		return G_SOURCE_CONTINUE;
3fc286
-	}
3fc286
-	else
3fc286
-	{
3fc286
-		return G_SOURCE_REMOVE;
3fc286
-	}
3fc286
+	selector->populate_listbox_id = 0;
3fc286
+	return G_SOURCE_REMOVE;
3fc286
 }
3fc286
 
3fc286
 static void
3fc286
 populate_liststore (GeditOpenDocumentSelector *selector)
3fc286
 {
3fc286
 	/* Populate requests are compressed */
3fc286
-	if (selector->populate_liststore_is_idle)
3fc286
+	if (selector->populate_listbox_id != 0)
3fc286
 	{
3fc286
 		DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: idle\n", selector););
3fc286
-
3fc286
-		selector->populate_scheduled = TRUE;
3fc286
 		return;
3fc286
 	}
3fc286
 
3fc286
 	DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: scheduled\n", selector););
3fc286
-
3fc286
-	selector->populate_liststore_is_idle = TRUE;
3fc286
-	gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30, real_populate_liststore, selector, NULL);
3fc286
+	selector->populate_listbox_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
3fc286
+								   real_populate_liststore,
3fc286
+								   selector,
3fc286
+								   NULL);
3fc286
 }
3fc286
 
3fc286
 static gboolean
3fc286
 on_treeview_key_press (GtkTreeView               *treeview,
3fc286
                        GdkEventKey               *event,
3fc286
                        GeditOpenDocumentSelector *selector)
3fc286
 {
3fc286
 	guint keyval;
3fc286
 	gboolean is_control_pressed;
3fc286
 	GtkTreeSelection *tree_selection;
3fc286
 	GtkTreePath *root_path;
3fc286
 	GdkModifierType modifiers;
3fc286
 
3fc286
 	if (gdk_event_get_keyval ((GdkEvent *)event, &keyval) == TRUE)
3fc286
 	{
3fc286
 		tree_selection = gtk_tree_view_get_selection (treeview);
3fc286
 		root_path = gtk_tree_path_new_from_string ("0");
3fc286
 
3fc286
 		modifiers = gtk_accelerator_get_default_mod_mask ();
3fc286
 		is_control_pressed = (event->state & modifiers) == GDK_CONTROL_MASK;
3fc286
 
3fc286
 		if ((keyval == GDK_KEY_Up || keyval == GDK_KEY_KP_Up) &&
3fc286
 		    !is_control_pressed)
3fc286
 		{
3fc286
 			if (gtk_tree_selection_path_is_selected (tree_selection, root_path))
3fc286
 			{
3fc286
 				gtk_tree_selection_unselect_all (tree_selection);
3fc286
 				gtk_widget_grab_focus (selector->search_entry);
3fc286
 
3fc286
 				return GDK_EVENT_STOP;
3fc286
@@ -683,66 +673,64 @@ on_entry_activated (GtkEntry                  *entry,
3fc286
 			uri = g_strconcat ("file://", entry_text, NULL);
3fc286
 		}
3fc286
 	}
3fc286
 	else
3fc286
 	{
3fc286
 		g_free (scheme);
3fc286
 		uri = g_strdup (entry_text);
3fc286
 	}
3fc286
 
3fc286
 	file = g_file_new_for_uri (uri);
3fc286
 	if (g_file_query_exists (file, NULL))
3fc286
 	{
3fc286
 		DEBUG_SELECTOR (g_print ("Selector(%p): search entry activated : loading '%s'\n",
3fc286
 		                         selector, uri););
3fc286
 
3fc286
 		gtk_entry_set_text (entry, "");
3fc286
 		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector->treeview));
3fc286
 		gtk_tree_selection_unselect_all (selection);
3fc286
 
3fc286
 		g_signal_emit (G_OBJECT (selector), signals[SELECTOR_FILE_ACTIVATED], 0, uri);
3fc286
 	}
3fc286
 
3fc286
 	g_object_unref (file);
3fc286
 }
3fc286
 
3fc286
 static void
3fc286
 gedit_open_document_selector_dispose (GObject *object)
3fc286
 {
3fc286
 	GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
3fc286
 
3fc286
-	while (TRUE)
3fc286
+	if (selector->populate_listbox_id != 0)
3fc286
 	{
3fc286
-		if (!g_idle_remove_by_data (selector))
3fc286
-		{
3fc286
-			break;
3fc286
-		}
3fc286
+		g_source_remove (selector->populate_listbox_id);
3fc286
+		selector->populate_listbox_id = 0;
3fc286
 	}
3fc286
 
3fc286
 	g_clear_pointer (&selector->name_font, pango_font_description_free);
3fc286
 	g_clear_pointer (&selector->path_font, pango_font_description_free);
3fc286
 
3fc286
 	if (selector->recent_items)
3fc286
 	{
3fc286
 		gedit_open_document_selector_free_file_items_list (selector->recent_items);
3fc286
 		selector->recent_items = NULL;
3fc286
 	}
3fc286
 
3fc286
 	if (selector->home_dir_items)
3fc286
 	{
3fc286
 		gedit_open_document_selector_free_file_items_list (selector->home_dir_items);
3fc286
 		selector->home_dir_items = NULL;
3fc286
 	}
3fc286
 
3fc286
 	if (selector->desktop_dir_items)
3fc286
 	{
3fc286
 		gedit_open_document_selector_free_file_items_list (selector->desktop_dir_items);
3fc286
 		selector->desktop_dir_items = NULL;
3fc286
 	}
3fc286
 
3fc286
 	if (selector->local_bookmarks_dir_items)
3fc286
 	{
3fc286
 		gedit_open_document_selector_free_file_items_list (selector->local_bookmarks_dir_items);
3fc286
 		selector->local_bookmarks_dir_items = NULL;
3fc286
 	}
3fc286
 
3fc286
 	if (selector->file_browser_root_items)
3fc286
-- 
3fc286
2.25.1
3fc286