]> Pileus Git - ~andy/gtk/commitdiff
app-chooser-dialog: make sure to hold a ref when doing async ops
authorCosimo Cecchi <cosimoc@gnome.org>
Wed, 1 Feb 2012 18:16:06 +0000 (13:16 -0500)
committerCosimo Cecchi <cosimoc@gnome.org>
Wed, 1 Feb 2012 18:21:43 +0000 (13:21 -0500)
Hold a ref to the GtkDialog while doing async operations with the
GtkAppChooserOnline object.
This is needed, since somebody could call gtk_widget_destroy() on us
while an async operation is in progress. We don't want to be finalized
in that case, but mark the fact that we were dismissed and just return
from the callback in that case.
This avoids crashing if the dialog is destroyed in the middle of a PK
operation.

https://bugzilla.gnome.org/show_bug.cgi?id=649121

gtk/gtkappchooserdialog.c

index 8d03cc00c921de8d4c8bb5cd7ace9979a5b117e9..c0ee59ceaa925c34dfb2d29f5756e851df962885 100644 (file)
@@ -80,6 +80,7 @@ struct _GtkAppChooserDialogPrivate {
   GCancellable *online_cancellable;
 
   gboolean show_more_clicked;
+  gboolean dismissed;
 };
 
 enum {
@@ -129,6 +130,9 @@ search_for_mimetype_ready_cb (GObject      *source,
 
   _gtk_app_chooser_online_search_for_mimetype_finish (online, res, &error);
 
+  if (self->priv->dismissed)
+    goto out;
+
   if (error != NULL &&
       !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
     {
@@ -141,7 +145,9 @@ search_for_mimetype_ready_cb (GObject      *source,
       gtk_app_chooser_refresh (GTK_APP_CHOOSER (self->priv->app_chooser_widget));
     }
 
+ out:
   g_clear_error (&error);
+  g_object_unref (self);
 
   gdk_threads_leave ();
 }
@@ -160,7 +166,7 @@ online_button_clicked_cb (GtkButton *b,
                                                     GTK_WINDOW (self),
                                                      self->priv->online_cancellable,
                                                     search_for_mimetype_ready_cb,
-                                                    self);
+                                                    g_object_ref (self));
 }
 
 static void
@@ -174,7 +180,8 @@ app_chooser_online_get_default_ready_cb (GObject *source,
 
   self->priv->online = _gtk_app_chooser_online_get_default_finish (source, res);
 
-  if (self->priv->online != NULL)
+  if (self->priv->online != NULL &&
+      !self->priv->dismissed)
     {
       GtkWidget *action_area;
 
@@ -194,13 +201,16 @@ app_chooser_online_get_default_ready_cb (GObject *source,
       gtk_widget_show (self->priv->online_button);
     }
 
+  g_object_unref (self);
+
   gdk_threads_leave ();
 }
 
 static void
 ensure_online_button (GtkAppChooserDialog *self)
 {
-  _gtk_app_chooser_online_get_default_async (app_chooser_online_get_default_ready_cb, self);
+  _gtk_app_chooser_online_get_default_async (app_chooser_online_get_default_ready_cb,
+                                             g_object_ref (self));
 }
 
 /* An application is valid if:
@@ -298,6 +308,9 @@ gtk_app_chooser_dialog_response (GtkDialog *dialog,
     case GTK_RESPONSE_OK:
       add_or_find_application (self);
       break;
+    case GTK_RESPONSE_CANCEL:
+    case GTK_RESPONSE_DELETE_EVENT:
+      self->priv->dismissed = TRUE;
     default :
       break;
     }