[gnome-control-center] power: Use GCancellable better, to avoid a crash



commit 5f353fa2b6d44a4be4e601b25f712e73736cd4c2
Author: Michael Terry <michael terry canonical com>
Date:   Fri Sep 7 15:37:42 2012 -0400

    power: Use GCancellable better, to avoid a crash
    
    https://bugzilla.gnome.org/show_bug.cgi?id=683533

 panels/power/cc-power-panel.c |   37 ++++++++++++++++++++++---------------
 1 files changed, 22 insertions(+), 15 deletions(-)
---
diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c
index 2b7e0ae..7d9c9a1 100644
--- a/panels/power/cc-power-panel.c
+++ b/panels/power/cc-power-panel.c
@@ -91,6 +91,7 @@ cc_power_panel_dispose (GObject *object)
     }
   if (priv->cancellable != NULL)
     {
+      g_cancellable_cancel (priv->cancellable);
       g_object_unref (priv->cancellable);
       priv->cancellable = NULL;
     }
@@ -114,14 +115,6 @@ cc_power_panel_dispose (GObject *object)
 }
 
 static void
-cc_power_panel_finalize (GObject *object)
-{
-  CcPowerPanelPrivate *priv = CC_POWER_PANEL (object)->priv;
-  g_cancellable_cancel (priv->cancellable);
-  G_OBJECT_CLASS (cc_power_panel_parent_class)->finalize (object);
-}
-
-static void
 on_lock_settings_changed (GSettings     *settings,
                           const char    *key,
                           CcPowerPanel *panel)
@@ -145,7 +138,6 @@ cc_power_panel_class_init (CcPowerPanelClass *klass)
   object_class->get_property = cc_power_panel_get_property;
   object_class->set_property = cc_power_panel_set_property;
   object_class->dispose = cc_power_panel_dispose;
-  object_class->finalize = cc_power_panel_finalize;
 
   panel_class->get_help_uri = cc_power_panel_get_help_uri;
 }
@@ -639,8 +631,8 @@ add_device_secondary (CcPowerPanel *panel,
 static void
 get_devices_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
-  CcPowerPanel *panel = CC_POWER_PANEL (user_data);
-  CcPowerPanelPrivate *priv = panel->priv;
+  CcPowerPanel *panel;
+  CcPowerPanelPrivate *priv;
   gboolean got_primary = FALSE;
   gboolean ups_as_primary_device = FALSE;
   GError *error = NULL;
@@ -656,6 +648,16 @@ get_devices_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
   UpDeviceKind kind;
   UpDeviceState state;
 
+  result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+  if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+    {
+      g_error_free (error);
+      return; /* Must exit before accessing freed memory */
+    }
+
+  panel = CC_POWER_PANEL (user_data);
+  priv = panel->priv;
+
   /* empty the secondary box */
   widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
                                                "grid_secondary"));
@@ -672,7 +674,6 @@ get_devices_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
                                                "box_secondary"));
   gtk_widget_hide (widget);
 
-  result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
   if (result == NULL)
     {
       g_printerr ("Error getting devices: %s\n", error->message);
@@ -771,16 +772,22 @@ static void
 got_power_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
   GError *error = NULL;
-  CcPowerPanelPrivate *priv = CC_POWER_PANEL (user_data)->priv;
+  GDBusProxy *proxy;
+  CcPowerPanelPrivate *priv;
 
-  priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
-  if (priv->proxy == NULL)
+  proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+  if (proxy == NULL)
     {
       g_printerr ("Error creating proxy: %s\n", error->message);
       g_error_free (error);
       return;
     }
 
+  /* Access user_data after checking for error because user_data might be
+     disposed already. */
+  priv = CC_POWER_PANEL (user_data)->priv;
+  priv->proxy = proxy;
+
   /* we want to change the primary device changes */
   g_signal_connect (priv->proxy,
                     "g-properties-changed",



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