Blame SOURCES/0016-iso-dialog-Avoid-crash-when-closing-dialog-early.patch

48c875
From eb6755e1ca400249d54582a7a763b3114e143e23 Mon Sep 17 00:00:00 2001
48c875
From: "Eduardo Lima (Etrunko)" <etrunko@redhat.com>
48c875
Date: Wed, 25 Jan 2017 17:41:20 -0200
48c875
Subject: [PATCH 16/26] iso-dialog: Avoid crash when closing dialog early
48c875
48c875
We must take into account that users can close the dialog at anytime,
48c875
even during an operation of fetch or set ISO has not been finished. This
48c875
will cause the callbacks for those operations to be invoked with an
48c875
invalid object, crashing the application.
48c875
48c875
To fix this issue we need to pass a GCancellable to the asynchronous
48c875
operations, so they can be cancelled if the dialog happens to get closed
48c875
before they complete.
48c875
48c875
NOTE: This patch triggers a deadlock in libgovirt when the dialog is
48c875
closed before the operation completes. Bug reported in
48c875
https://bugzilla.gnome.org/show_bug.cgi?id=777808. We will need to bump
48c875
libgovirt dependency whenever it has a new release.
48c875
48c875
Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
48c875
---
48c875
 src/remote-viewer-iso-list-dialog.c | 42 ++++++++++++++++++++++++++++++-------
48c875
 1 file changed, 34 insertions(+), 8 deletions(-)
48c875
48c875
diff --git a/src/remote-viewer-iso-list-dialog.c b/src/remote-viewer-iso-list-dialog.c
48c875
index 2ab5435..745768a 100644
48c875
--- a/src/remote-viewer-iso-list-dialog.c
48c875
+++ b/src/remote-viewer-iso-list-dialog.c
48c875
@@ -42,6 +42,7 @@ struct _RemoteViewerISOListDialogPrivate
48c875
     GtkWidget *stack;
48c875
     GtkWidget *tree_view;
48c875
     OvirtForeignMenu *foreign_menu;
48c875
+    GCancellable *cancellable;
48c875
 };
48c875
 
48c875
 enum RemoteViewerISOListDialogModel
48c875
@@ -66,6 +67,8 @@ remote_viewer_iso_list_dialog_dispose(GObject *object)
48c875
     RemoteViewerISOListDialog *self = REMOTE_VIEWER_ISO_LIST_DIALOG(object);
48c875
     RemoteViewerISOListDialogPrivate *priv = self->priv;
48c875
 
48c875
+    g_clear_object(&priv->cancellable);
48c875
+
48c875
     if (priv->foreign_menu) {
48c875
         g_signal_handlers_disconnect_by_data(priv->foreign_menu, object);
48c875
         g_clear_object(&priv->foreign_menu);
48c875
@@ -157,17 +160,24 @@ fetch_iso_names_cb(OvirtForeignMenu *foreign_menu,
48c875
         const gchar *msg = error ? error->message : _("Failed to fetch CD names");
48c875
         gchar *markup = g_strdup_printf("%s", msg);
48c875
 
48c875
+        g_debug("Error fetching ISO names: %s", msg);
48c875
+        if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
48c875
+            goto end;
48c875
+
48c875
         gtk_label_set_markup(GTK_LABEL(priv->status), markup);
48c875
         gtk_spinner_stop(GTK_SPINNER(priv->spinner));
48c875
         remote_viewer_iso_list_dialog_show_error(self, msg);
48c875
         gtk_dialog_set_response_sensitive(GTK_DIALOG(self), GTK_RESPONSE_NONE, TRUE);
48c875
         g_free(markup);
48c875
-        g_clear_error(&error);
48c875
-        return;
48c875
+        goto end;
48c875
     }
48c875
 
48c875
+    g_clear_object(&priv->cancellable);
48c875
     g_list_foreach(iso_list, (GFunc) remote_viewer_iso_list_dialog_foreach, self);
48c875
     remote_viewer_iso_list_dialog_show_files(self);
48c875
+
48c875
+end:
48c875
+    g_clear_error(&error);
48c875
 }
48c875
 
48c875
 
48c875
@@ -177,7 +187,10 @@ remote_viewer_iso_list_dialog_refresh_iso_list(RemoteViewerISOListDialog *self)
48c875
     RemoteViewerISOListDialogPrivate *priv = self->priv;
48c875
 
48c875
     gtk_list_store_clear(priv->list_store);
48c875
-    ovirt_foreign_menu_fetch_iso_names_async(priv->foreign_menu, NULL,
48c875
+
48c875
+    priv->cancellable = g_cancellable_new();
48c875
+    ovirt_foreign_menu_fetch_iso_names_async(priv->foreign_menu,
48c875
+                                             priv->cancellable,
48c875
                                              (GAsyncReadyCallback) fetch_iso_names_cb,
48c875
                                              self);
48c875
 }
48c875
@@ -190,8 +203,10 @@ remote_viewer_iso_list_dialog_response(GtkDialog *dialog,
48c875
     RemoteViewerISOListDialog *self = REMOTE_VIEWER_ISO_LIST_DIALOG(dialog);
48c875
     RemoteViewerISOListDialogPrivate *priv = self->priv;
48c875
 
48c875
-    if (response_id != GTK_RESPONSE_NONE)
48c875
+    if (response_id != GTK_RESPONSE_NONE) {
48c875
+        g_cancellable_cancel(priv->cancellable);
48c875
         return;
48c875
+    }
48c875
 
48c875
     gtk_spinner_start(GTK_SPINNER(priv->spinner));
48c875
     gtk_label_set_markup(GTK_LABEL(priv->status), _("Loading..."));
48c875
@@ -223,7 +238,9 @@ remote_viewer_iso_list_dialog_toggled(GtkCellRendererToggle *cell_renderer G_GNU
48c875
     gtk_dialog_set_response_sensitive(GTK_DIALOG(self), GTK_RESPONSE_NONE, FALSE);
48c875
     gtk_widget_set_sensitive(priv->tree_view, FALSE);
48c875
 
48c875
-    ovirt_foreign_menu_set_current_iso_name_async(priv->foreign_menu, active ? NULL : name, NULL,
48c875
+    priv->cancellable = g_cancellable_new();
48c875
+    ovirt_foreign_menu_set_current_iso_name_async(priv->foreign_menu, active ? NULL : name,
48c875
+                                                  priv->cancellable,
48c875
                                                   (GAsyncReadyCallback)ovirt_foreign_menu_iso_name_changed,
48c875
                                                   self);
48c875
     gtk_tree_path_free(tree_path);
48c875
@@ -308,12 +325,18 @@ ovirt_foreign_menu_iso_name_changed(OvirtForeignMenu *foreign_menu,
48c875
      * change the ISO back to the original, avoiding a possible inconsistency.
48c875
      */
48c875
     if (!ovirt_foreign_menu_set_current_iso_name_finish(foreign_menu, result, &error)) {
48c875
-        remote_viewer_iso_list_dialog_show_error(self, error ? error->message : _("Failed to change CD"));
48c875
-        g_clear_error(&error);
48c875
+        const gchar *msg = error ? error->message : _("Failed to change CD");
48c875
+        g_debug("Error changing ISO: %s", msg);
48c875
+
48c875
+        if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
48c875
+            goto end;
48c875
+
48c875
+        remote_viewer_iso_list_dialog_show_error(self, msg);
48c875
     }
48c875
 
48c875
+    g_clear_object(&priv->cancellable);
48c875
     if (!gtk_tree_model_get_iter_first(model, &iter))
48c875
-        return;
48c875
+        goto end;
48c875
 
48c875
     current_iso = ovirt_foreign_menu_get_current_iso_name(foreign_menu);
48c875
 
48c875
@@ -340,6 +363,9 @@ ovirt_foreign_menu_iso_name_changed(OvirtForeignMenu *foreign_menu,
48c875
     gtk_dialog_set_response_sensitive(GTK_DIALOG(self), GTK_RESPONSE_NONE, TRUE);
48c875
     gtk_widget_set_sensitive(priv->tree_view, TRUE);
48c875
     g_free(current_iso);
48c875
+
48c875
+end:
48c875
+    g_clear_error(&error);
48c875
 }
48c875
 
48c875
 GtkWidget *
48c875
-- 
48c875
2.12.0
48c875