summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2013-03-25 13:01:23 +0100
committerCarlos Garcia Campos <carlosgc@gnome.org>2013-03-25 14:59:06 +0100
commit73c6f82f5d05c6c108b9a9d9e8b29d11f91deb58 (patch)
treec0adefee3b75b65d4a0830b31502431b184237a2
parent2f555ca1556105e3a214acd8d6665f2b281fb526 (diff)
downloadgtk+-73c6f82f5d05c6c108b9a9d9e8b29d11f91deb58.tar.gz
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
-rw-r--r--modules/printbackends/cups/gtkprintbackendcups.c90
1 files changed, 51 insertions, 39 deletions
diff --git a/modules/printbackends/cups/gtkprintbackendcups.c b/modules/printbackends/cups/gtkprintbackendcups.c
index 45aa007bce..80d868c83d 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