[gtk+] gtkprintbackendcups: Fix a crash in avahi_create_browsers()



commit 5701681df478f620e889171d8780e013535aa7d8
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Mon Mar 25 13:01:23 2013 +0100

    gtkprintbackendcups: Fix a crash in avahi_create_browsers()
    
    In avahi_request_printer_list() a new connection to the DBus system bus
    is started asynchronously, but it's not cancellable and it's not taking
    any reference of the GtkPrintBackendCups. This means that when the
    callback is called, the object might have been destroyed already. We can
    just pass the cancellable created and check for the cancelled error in
    the callback before trying to use the GtkPrintBackendCups. The code to
    cancel avahi operations and to unsibscribe from the DBus signals has
    been moved from finalize to dispose to make sure it happens as soon as
    possible.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=696553

 modules/printbackends/cups/gtkprintbackendcups.c |   90 ++++++++++++---------
 1 files changed, 51 insertions(+), 39 deletions(-)
---
diff --git a/modules/printbackends/cups/gtkprintbackendcups.c 
b/modules/printbackends/cups/gtkprintbackendcups.c
index 45aa007..80d868c 100644
--- a/modules/printbackends/cups/gtkprintbackendcups.c
+++ b/modules/printbackends/cups/gtkprintbackendcups.c
@@ -787,9 +787,6 @@ static void
 gtk_print_backend_cups_finalize (GObject *object)
 {
   GtkPrintBackendCups *backend_cups;
-#ifdef HAVE_CUPS_API_1_6
-  gint                 i;
-#endif
 
   GTK_NOTE (PRINTING,
             g_print ("CUPS Backend: finalizing CUPS backend module\n"));
@@ -814,6 +811,37 @@ gtk_print_backend_cups_finalize (GObject *object)
 #endif
 
 #ifdef HAVE_CUPS_API_1_6
+  g_clear_object (&backend_cups->avahi_cancellable);
+  g_clear_pointer (&backend_cups->avahi_default_printer, g_free);
+  g_clear_object (&backend_cups->dbus_connection);
+#endif
+
+  backend_parent_class->finalize (object);
+}
+
+static void
+gtk_print_backend_cups_dispose (GObject *object)
+{
+  GtkPrintBackendCups *backend_cups;
+#ifdef HAVE_CUPS_API_1_6
+  gint                 i;
+#endif
+
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
+  backend_cups = GTK_PRINT_BACKEND_CUPS (object);
+
+  if (backend_cups->list_printers_poll > 0)
+    g_source_remove (backend_cups->list_printers_poll);
+  backend_cups->list_printers_poll = 0;
+  backend_cups->list_printers_attempts = 0;
+
+  if (backend_cups->default_printer_poll > 0)
+    g_source_remove (backend_cups->default_printer_poll);
+  backend_cups->default_printer_poll = 0;
+
+#ifdef HAVE_CUPS_API_1_6
   g_cancellable_cancel (backend_cups->avahi_cancellable);
 
   for (i = 0; i < 2; i++)
@@ -849,34 +877,8 @@ gtk_print_backend_cups_finalize (GObject *object)
                                             backend_cups->avahi_service_browser_subscription_id);
       backend_cups->avahi_service_browser_subscription_id = 0;
     }
-
-  g_clear_object (&backend_cups->avahi_cancellable);
-  g_clear_pointer (&backend_cups->avahi_default_printer, g_free);
-  g_clear_object (&backend_cups->dbus_connection);
 #endif
 
-  backend_parent_class->finalize (object);
-}
-
-static void
-gtk_print_backend_cups_dispose (GObject *object)
-{
-  GtkPrintBackendCups *backend_cups;
-
-  GTK_NOTE (PRINTING,
-            g_print ("CUPS Backend: %s\n", G_STRFUNC));
-
-  backend_cups = GTK_PRINT_BACKEND_CUPS (object);
-
-  if (backend_cups->list_printers_poll > 0)
-    g_source_remove (backend_cups->list_printers_poll);
-  backend_cups->list_printers_poll = 0;
-  backend_cups->list_printers_attempts = 0;
-
-  if (backend_cups->default_printer_poll > 0)
-    g_source_remove (backend_cups->default_printer_poll);
-  backend_cups->default_printer_poll = 0;
-
   backend_parent_class->dispose (object);
 }
 
@@ -2609,7 +2611,7 @@ avahi_service_resolver_cb (GObject      *source_object,
                            gpointer      user_data)
 {
   AvahiConnectionTestData *data;
-  GtkPrintBackendCups     *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  GtkPrintBackendCups     *backend;
   const gchar             *name;
   const gchar             *host;
   const gchar             *type;
@@ -2634,6 +2636,8 @@ avahi_service_resolver_cb (GObject      *source_object,
                                           &error);
   if (output)
     {
+      backend = GTK_PRINT_BACKEND_CUPS (user_data);
+
       g_variant_get (output, "(ii&s&s&s&si&sq aayu)",
                      &interface,
                      &protocol,
@@ -2702,7 +2706,8 @@ avahi_service_resolver_cb (GObject      *source_object,
     }
   else
     {
-      g_warning ("%s", error->message);
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_warning ("%s", error->message);
       g_error_free (error);
     }
 }
@@ -2805,7 +2810,7 @@ avahi_service_browser_new_cb (GObject      *source_object,
                               GAsyncResult *res,
                               gpointer      user_data)
 {
-  GtkPrintBackendCups *cups_backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  GtkPrintBackendCups *cups_backend;
   GVariant            *output;
   GError              *error = NULL;
   gint                 i;
@@ -2815,6 +2820,7 @@ avahi_service_browser_new_cb (GObject      *source_object,
                                           &error);
   if (output)
     {
+      cups_backend = GTK_PRINT_BACKEND_CUPS (user_data);
       i = cups_backend->avahi_service_browser_paths[0] ? 1 : 0;
 
       g_variant_get (output, "(o)", &cups_backend->avahi_service_browser_paths[i]);
@@ -2853,8 +2859,8 @@ avahi_service_browser_new_cb (GObject      *source_object,
        * The creation of ServiceBrowser fails with G_IO_ERROR_DBUS_ERROR
        * if Avahi is disabled.
        */
-      if (error->domain != G_IO_ERROR ||
-          error->code != G_IO_ERROR_DBUS_ERROR)
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR) &&
+          !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
         g_warning ("%s", error->message);
       g_error_free (error);
     }
@@ -2865,17 +2871,23 @@ avahi_create_browsers (GObject      *source_object,
                        GAsyncResult *res,
                        gpointer      user_data)
 {
-  GtkPrintBackendCups *cups_backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  GDBusConnection     *dbus_connection;
+  GtkPrintBackendCups *cups_backend;
   GError              *error = NULL;
 
-  cups_backend->dbus_connection = g_bus_get_finish (res, &error);
-  if (!cups_backend->dbus_connection)
+  dbus_connection = g_bus_get_finish (res, &error);
+  if (!dbus_connection)
     {
-      g_debug ("Couldn't connect to D-Bus system bus, %s", error->message);
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_warning ("Couldn't connect to D-Bus system bus, %s", error->message);
+
       g_error_free (error);
       return;
     }
 
+  cups_backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  cups_backend->dbus_connection = dbus_connection;
+
   /*
    * We need to subscribe to signals of service browser before
    * we actually create it because it starts to emit them right
@@ -2937,7 +2949,7 @@ static void
 avahi_request_printer_list (GtkPrintBackendCups *cups_backend)
 {
   cups_backend->avahi_cancellable = g_cancellable_new ();
-  g_bus_get (G_BUS_TYPE_SYSTEM, NULL, avahi_create_browsers, cups_backend);
+  g_bus_get (G_BUS_TYPE_SYSTEM, cups_backend->avahi_cancellable, avahi_create_browsers, cups_backend);
 }
 #endif
 


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