|
|
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 |
|