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

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