[gnome-control-center] printers: Make the cups connection test cancellable



commit 2ff5cfd6aa412688737dffc4f8699fbe67259507
Author: Felipe Borges <felipeborges gnome org>
Date:   Tue Jan 23 18:32:00 2018 +0100

    printers: Make the cups connection test cancellable
    
    Currently gnome-control-center could crash whenever a connection
    test is interrupted by the disposal of the Printers panel.
    
    Searching in the g-c-c shell for any query that could match the
    Printers panel would instantiate the CcPrintersPanel class. Since
    we perform a connection test to the printing server as soon as this
    object is created, a fast disposal of the panel (by choosing another
    search result) would cause the whole application to crash.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=792753

 panels/printers/cc-printers-panel.c | 27 +++++++++++++++++++++------
 panels/printers/pp-cups.c           | 16 +++++++++++-----
 panels/printers/pp-cups.h           |  4 +++-
 3 files changed, 35 insertions(+), 12 deletions(-)
---
diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c
index e2475737e..f24f29861 100644
--- a/panels/printers/cc-printers-panel.c
+++ b/panels/printers/cc-printers-panel.c
@@ -95,6 +95,7 @@ struct _CcPrintersPanelPrivate
   GCancellable *get_all_ppds_cancellable;
   GCancellable *subscription_renew_cancellable;
   GCancellable *actualize_printers_list_cancellable;
+  GCancellable *cups_status_check_cancellable;
 
   gchar    *new_printer_name;
   gchar    *new_printer_location;
@@ -242,6 +243,9 @@ cc_printers_panel_dispose (GObject *object)
 
   detach_from_cups_notifier (CC_PRINTERS_PANEL (object));
 
+  g_cancellable_cancel (priv->cups_status_check_cancellable);
+  g_clear_object (&priv->cups_status_check_cancellable);
+
   if (priv->cups_status_check_id > 0)
     {
       g_source_remove (priv->cups_status_check_id);
@@ -809,7 +813,7 @@ set_current_page (GObject      *source_object,
 
   priv = PRINTERS_PANEL_PRIVATE (self);
 
-  success = pp_cups_connection_test_finish (cups, result);
+  success = pp_cups_connection_test_finish (cups, result, NULL);
   g_object_unref (source_object);
 
   widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "main-vbox");
@@ -857,7 +861,7 @@ actualize_printers_list_cb (GObject      *source_object,
 
   widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "main-vbox");
   if (priv->num_dests == 0 && !priv->new_printer_name)
-    pp_cups_connection_test_async (g_object_ref (cups), set_current_page, self);
+    pp_cups_connection_test_async (g_object_ref (cups), NULL, set_current_page, self);
   else
     gtk_stack_set_visible_child_name (GTK_STACK (widget), "printers-list");
 
@@ -1095,7 +1099,7 @@ cups_status_check_cb (GObject      *source_object,
 
   priv = self->priv;
 
-  success = pp_cups_connection_test_finish (cups, result);
+  success = pp_cups_connection_test_finish (cups, result, NULL);
   if (success)
     {
       actualize_printers_list (self);
@@ -1118,7 +1122,7 @@ cups_status_check (gpointer user_data)
   priv = self->priv;
 
   cups = pp_cups_new ();
-  pp_cups_connection_test_async (cups, cups_status_check_cb, self);
+  pp_cups_connection_test_async (cups, NULL, cups_status_check_cb, self);
 
   return priv->cups_status_check_id != 0;
 }
@@ -1132,10 +1136,20 @@ connection_test_cb (GObject      *source_object,
   CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
   gboolean                success;
   PpCups                 *cups = PP_CUPS (source_object);
+  g_autoptr(GError)       error = NULL;
 
   priv = self->priv;
 
-  success = pp_cups_connection_test_finish (cups, result);
+  success = pp_cups_connection_test_finish (cups, result, &error);
+
+  if (error != NULL)
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        {
+          g_warning ("Could not test connection: %s", error->message);
+        }
+    }
+
   if (!success)
     {
       priv->cups_status_check_id =
@@ -1264,6 +1278,7 @@ cc_printers_panel_init (CcPrintersPanel *self)
                                                  NULL);
 
   priv->actualize_printers_list_cancellable = g_cancellable_new ();
+  priv->cups_status_check_cancellable = g_cancellable_new ();
 
   builder_result = gtk_builder_add_objects_from_resource (priv->builder,
                                                           "/org/gnome/control-center/printers/printers.ui",
@@ -1354,7 +1369,7 @@ Please check your installation");
                       self);
 
   cups = pp_cups_new ();
-  pp_cups_connection_test_async (cups, connection_test_cb, self);
+  pp_cups_connection_test_async (cups, priv->cups_status_check_cancellable, connection_test_cb, self);
   gtk_container_add (GTK_CONTAINER (self), top_widget);
   gtk_widget_show_all (GTK_WIDGET (self));
 }
diff --git a/panels/printers/pp-cups.c b/panels/printers/pp-cups.c
index 0d0d4a52b..628d8ae8a 100644
--- a/panels/printers/pp-cups.c
+++ b/panels/printers/pp-cups.c
@@ -112,19 +112,24 @@ connection_test_thread (GTask        *task,
   http_t *http;
 
   http = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ());
-  g_task_return_boolean (task, http != NULL);
-
   httpClose (http);
+
+  if (g_task_set_return_on_cancel (task, FALSE))
+    {
+      g_task_return_boolean (task, http != NULL);
+    }
 }
 
 void
 pp_cups_connection_test_async (PpCups              *cups,
+                               GCancellable        *cancellable,
                                GAsyncReadyCallback  callback,
                                gpointer             user_data)
 {
   GTask *task;
 
-  task = g_task_new (cups, NULL, callback, user_data);
+  task = g_task_new (cups, cancellable, callback, user_data);
+  g_task_set_return_on_cancel (task, TRUE);
   g_task_run_in_thread (task, connection_test_thread);
 
   g_object_unref (task);
@@ -132,11 +137,12 @@ pp_cups_connection_test_async (PpCups              *cups,
 
 gboolean
 pp_cups_connection_test_finish (PpCups         *cups,
-                                GAsyncResult   *result)
+                                GAsyncResult   *result,
+                                GError        **error)
 {
   g_return_val_if_fail (g_task_is_valid (result, cups), FALSE);
 
-  return g_task_propagate_boolean (G_TASK (result), NULL);
+  return g_task_propagate_boolean (G_TASK (result), error);
 }
 
 /* Cancels subscription of given id */
diff --git a/panels/printers/pp-cups.h b/panels/printers/pp-cups.h
index 863ca0011..c446febb9 100644
--- a/panels/printers/pp-cups.h
+++ b/panels/printers/pp-cups.h
@@ -66,11 +66,13 @@ PpCupsDests *pp_cups_get_dests_finish (PpCups               *cups,
                                        GError              **error);
 
 void         pp_cups_connection_test_async (PpCups              *cups,
+                                            GCancellable        *cancellable,
                                             GAsyncReadyCallback  callback,
                                             gpointer             user_data);
 
 gboolean     pp_cups_connection_test_finish (PpCups         *cups,
-                                             GAsyncResult   *result);
+                                             GAsyncResult   *result,
+                                             GError        **error);
 
 void         pp_cups_cancel_subscription_async    (PpCups              *cups,
                                                    gint                 subscription_id,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]