[at-spi2-atk] Fixed some problems when shutting down and restarting the module



commit a1a316d1ef4167dbca147bc3477ed22305c83743
Author: Mike Gorse <mgorse novell com>
Date:   Mon Aug 15 14:22:02 2011 -0500

    Fixed some problems when shutting down and restarting the module
    
    If gnome_accessibility_module_shutdown was called and followed by a call
    to gnome_accessibility_module_init, then things would go awry because of
    various resources not being freed.  Fixed several of these issues,
    although some issues might remain.

 atk-adaptor/accessible-cache.c       |   14 +++++-
 atk-adaptor/accessible-cache.h       |    2 +
 atk-adaptor/accessible-leasing.c     |    4 +-
 atk-adaptor/accessible-register.c    |   29 ++++++++----
 atk-adaptor/accessible-register.h    |    2 +-
 atk-adaptor/adaptors/cache-adaptor.c |   14 ++----
 atk-adaptor/bridge.c                 |   76 ++++++++++++++++++++++------------
 atk-adaptor/event.c                  |   12 ++++--
 droute/droute.c                      |   27 ++++++++++++
 droute/droute.h                      |    9 ++++
 10 files changed, 135 insertions(+), 54 deletions(-)
---
diff --git a/atk-adaptor/accessible-cache.c b/atk-adaptor/accessible-cache.c
index ad39819..4d5cdb3 100644
--- a/atk-adaptor/accessible-cache.c
+++ b/atk-adaptor/accessible-cache.c
@@ -125,8 +125,8 @@ spi_cache_init (SpiCache * cache)
 
   add_subtree (cache, spi_global_app_data->root);
 
-  atk_add_global_event_listener (child_added_listener,
-                                 "Gtk:AtkObject:children-changed");
+  cache->child_added_listener = atk_add_global_event_listener (child_added_listener,
+                                                               "Gtk:AtkObject:children-changed"); 
 
   g_signal_connect (G_OBJECT (spi_global_app_data->root),
                     "children-changed::add",
@@ -141,7 +141,15 @@ spi_cache_finalize (GObject * object)
   while (!g_queue_is_empty (cache->add_traversal))
     g_object_unref (G_OBJECT (g_queue_pop_head (cache->add_traversal)));
   g_queue_free (cache->add_traversal);
-  g_free (cache->objects);
+  g_hash_table_unref (cache->objects);
+
+  g_signal_handlers_disconnect_by_func (spi_global_register,
+                                        (GCallback) remove_object, cache);
+
+  g_signal_handlers_disconnect_by_func (G_OBJECT (spi_global_app_data->root),
+                                        (GCallback) toplevel_added_listener, NULL);
+
+  atk_remove_global_event_listener (cache->child_added_listener);
 
   G_OBJECT_CLASS (spi_cache_parent_class)->finalize (object);
 }
diff --git a/atk-adaptor/accessible-cache.h b/atk-adaptor/accessible-cache.h
index 1089c6f..2f5be06 100644
--- a/atk-adaptor/accessible-cache.h
+++ b/atk-adaptor/accessible-cache.h
@@ -44,6 +44,8 @@ struct _SpiCache
   GHashTable * objects;
   GQueue *add_traversal;
   gint add_pending_idle;
+
+  guint child_added_listener;
 };
 
 struct _SpiCacheClass
diff --git a/atk-adaptor/accessible-leasing.c b/atk-adaptor/accessible-leasing.c
index f4d0e2f..4370bff 100644
--- a/atk-adaptor/accessible-leasing.c
+++ b/atk-adaptor/accessible-leasing.c
@@ -72,7 +72,9 @@ spi_leasing_finalize (GObject * object)
 {
   SpiLeasing *leasing = SPI_LEASING (object);
 
-  g_free (leasing->expiry_queue);
+  if (leasing->expiry_func_id)
+    g_source_remove (leasing->expiry_func_id);
+  g_queue_free (leasing->expiry_queue);
   G_OBJECT_CLASS (spi_leasing_parent_class)->finalize (object);
 }
 
diff --git a/atk-adaptor/accessible-register.c b/atk-adaptor/accessible-register.c
index 83c1c6d..14f256f 100644
--- a/atk-adaptor/accessible-register.c
+++ b/atk-adaptor/accessible-register.c
@@ -121,11 +121,26 @@ spi_register_init (SpiRegister * reg)
 }
 
 static void
+deregister_object (gpointer data, GObject * gobj)
+{
+  SpiRegister *reg = SPI_REGISTER (data);
+
+  spi_register_deregister_object (reg, gobj, FALSE);
+}
+
+static void
+spi_register_remove_weak_ref (gpointer key, gpointer val, gpointer reg)
+{
+  g_object_weak_unref (val, deregister_object, reg);
+}
+
+static void
 spi_register_finalize (GObject * object)
 {
   SpiRegister *reg = SPI_REGISTER (object);
 
-  g_free (reg->ref2ptr);
+  g_hash_table_foreach (reg->ref2ptr, spi_register_remove_weak_ref, reg);
+  g_hash_table_unref (reg->ref2ptr);
 
   G_OBJECT_CLASS (spi_register_parent_class)->finalize (object);
 }
@@ -186,16 +201,8 @@ ref_to_path (guint ref)
  * Removes the AtkObject from the reference lookup tables, meaning
  * it is no longer exposed over D-Bus.
  */
-static void
-deregister_object (gpointer data, GObject * gobj)
-{
-  SpiRegister *reg = SPI_REGISTER (data);
-
-  spi_register_deregister_object (reg, gobj);
-}
-
 void
-spi_register_deregister_object (SpiRegister *reg, GObject *gobj)
+spi_register_deregister_object (SpiRegister *reg, GObject *gobj, gboolean unref)
 {
   guint ref;
 
@@ -206,6 +213,8 @@ spi_register_deregister_object (SpiRegister *reg, GObject *gobj)
                      register_signals [OBJECT_DEREGISTERED],
                      0,
                      gobj);
+      if (unref)
+        g_object_weak_unref (gobj, deregister_object, reg);
       g_hash_table_remove (reg->ref2ptr, GINT_TO_POINTER (ref));
 
 #ifdef SPI_ATK_DEBUG
diff --git a/atk-adaptor/accessible-register.h b/atk-adaptor/accessible-register.h
index edbe3c2..5a62ebb 100644
--- a/atk-adaptor/accessible-register.h
+++ b/atk-adaptor/accessible-register.h
@@ -73,7 +73,7 @@ gchar *
 spi_register_root_object_path ();
 
 void
-spi_register_deregister_object (SpiRegister *reg, GObject *gobj);
+spi_register_deregister_object (SpiRegister *reg, GObject *gobj, gboolean unref);
 
 /*---------------------------------------------------------------------------*/
 
diff --git a/atk-adaptor/adaptors/cache-adaptor.c b/atk-adaptor/adaptors/cache-adaptor.c
index 3b5540c..e221920 100644
--- a/atk-adaptor/adaptors/cache-adaptor.c
+++ b/atk-adaptor/adaptors/cache-adaptor.c
@@ -318,15 +318,11 @@ spi_initialize_cache (DRoutePath * path)
 {
   droute_path_add_interface (path, ATSPI_DBUS_INTERFACE_CACHE, spi_org_a11y_atspi_Cache, methods, NULL);
 
-  g_signal_connect (spi_global_cache,
-                    "object-added",
-                    (GCallback) emit_cache_add,
-                    NULL);
-
-  g_signal_connect (spi_global_cache,
-                    "object-removed",
-                    (GCallback) emit_cache_remove,
-                    NULL);
+  g_signal_connect (spi_global_cache, "object-added",
+                    (GCallback) emit_cache_add, NULL);
+
+  g_signal_connect (spi_global_cache, "object-removed",
+                    (GCallback) emit_cache_remove, NULL);
 };
 
 /*END------------------------------------------------------------------------*/
diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c
index bcae3b9..d049731 100644
--- a/atk-adaptor/bridge.c
+++ b/atk-adaptor/bridge.c
@@ -54,6 +54,9 @@
 
 /*---------------------------------------------------------------------------*/
 
+static DBusHandlerResult
+signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data);
+
 SpiBridge *spi_global_app_data = NULL;
 
 /*static Display *bridge_display = NULL;*/
@@ -301,28 +304,6 @@ deregister_application (SpiBridge * app)
 
 /*---------------------------------------------------------------------------*/
 
-static void
-exit_func (void)
-{
-  if (!spi_global_app_data)
-    {
-      return;
-    }
-
-  spi_atk_tidy_windows ();
-  spi_atk_deregister_event_listeners ();
-  deregister_application (spi_global_app_data);
-
-  g_free (spi_global_app_data);
-  spi_global_app_data = NULL;
-
-  /* Not currently creating an XDisplay */
-#if 0
-  if (bridge_display)
-    XCloseDisplay (bridge_display);
-#endif
-}
-
 /*---------------------------------------------------------------------------*/
 
 static AtkPlugClass *plug_class;
@@ -498,9 +479,7 @@ new_connection_cb (DBusServer *server, DBusConnection *con, void *data)
   droute_intercept_dbus (con);
   droute_context_register (spi_global_app_data->droute, con);
 
-  new_list = g_list_append (spi_global_app_data->direct_connections, con);
-  if (new_list)
-    spi_global_app_data->direct_connections = new_list;
+  spi_global_app_data->direct_connections = g_list_append (spi_global_app_data->direct_connections, con);
 }
 
 static int
@@ -851,8 +830,53 @@ gnome_accessibility_module_init (void)
 void
 gnome_accessibility_module_shutdown (void)
 {
+  GList *l;
+
+  if (!spi_global_app_data)
+      return;
+
+  spi_atk_tidy_windows ();
   spi_atk_deregister_event_listeners ();
-  exit_func ();
+
+  deregister_application (spi_global_app_data);
+
+  if (spi_global_app_data->bus)
+    {
+      dbus_connection_remove_filter (spi_global_app_data->bus, signal_filter, NULL);
+      droute_context_unregister (spi_global_app_data->droute, spi_global_app_data->bus);
+      dbus_connection_unref (spi_global_app_data->bus);
+    }
+
+  for (l = spi_global_app_data->direct_connections; l; l = l->next)
+    {
+      droute_context_unregister (spi_global_app_data->droute, l->data);
+      droute_unintercept_dbus (l->data);
+      dbus_connection_unref (l);
+    }
+  g_list_free (spi_global_app_data->direct_connections);
+
+  for (l = clients; l; l = l->next)
+     g_free (l->data);
+  g_list_free (clients);
+  clients = NULL;
+
+  g_object_unref (spi_global_cache);
+  g_object_unref (spi_global_leasing);
+  g_object_unref (spi_global_register);
+
+  if (spi_global_app_data->main_context)
+    g_main_context_unref (spi_global_app_data->main_context);
+
+  droute_free (spi_global_app_data->droute);
+
+  g_free (spi_global_app_data);
+  spi_global_app_data = NULL;
+
+  /* Not currently creating an XDisplay */
+#if 0
+  if (bridge_display)
+    XCloseDisplay (bridge_display);
+#endif
 }
 
 static gchar *name_match_tmpl =
diff --git a/atk-adaptor/event.c b/atk-adaptor/event.c
index f5a2d2d..e940e00 100644
--- a/atk-adaptor/event.c
+++ b/atk-adaptor/event.c
@@ -613,7 +613,8 @@ state_event_listener (GSignalInvocationHint * signal_hint,
               DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
 
   if (!g_strcmp0 (pname, "defunct"))
-    spi_register_deregister_object (spi_global_register, G_OBJECT (accessible));
+    spi_register_deregister_object (spi_global_register, G_OBJECT (accessible),
+                                    TRUE);
   return TRUE;
 }
 
@@ -1194,11 +1195,14 @@ spi_atk_deregister_event_listeners (void)
     atk_bridge_focus_tracker_id = 0;
   }
 
-  for (i = 0; ids && i < ids->len; i++)
+  if (ids)
     {
-      atk_remove_global_event_listener (g_array_index (ids, guint, i));
+      for (i = 0; i < ids->len; i++)
+        {
+          atk_remove_global_event_listener (g_array_index (ids, guint, i));
+        }
+      g_array_free (ids, TRUE);
     }
-  g_array_free (ids, TRUE);
 
   if (atk_bridge_key_event_listener_id)
   {
diff --git a/droute/droute.c b/droute/droute.c
index 20c262f..9212e4d 100644
--- a/droute/droute.c
+++ b/droute/droute.c
@@ -686,6 +686,12 @@ droute_path_register (DRoutePath *path, DBusConnection *bus)
 }
 
 void
+droute_path_unregister (DRoutePath *path, DBusConnection *bus)
+{
+  dbus_connection_unregister_object_path (bus, path->path);
+}
+
+void
 droute_context_register (DRouteContext *cnx, DBusConnection *bus)
 {
     g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_register,
@@ -693,9 +699,30 @@ droute_context_register (DRouteContext *cnx, DBusConnection *bus)
 }
 
 void
+droute_context_unregister (DRouteContext *cnx, DBusConnection *bus)
+{
+    g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister,
+                         bus);
+}
+
+void
+droute_context_deregister (DRouteContext *cnx, DBusConnection *bus)
+{
+    g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister,
+                         bus);
+}
+
+void
 droute_intercept_dbus (DBusConnection *bus)
 {
     dbus_connection_register_object_path (bus, DBUS_PATH_DBUS,
                                           &droute_vtable, NULL);
 }
+
+void
+droute_unintercept_dbus (DBusConnection *bus)
+{
+    dbus_connection_unregister_object_path (bus, DBUS_PATH_DBUS);
+}
+
 /*END------------------------------------------------------------------------*/
diff --git a/droute/droute.h b/droute/droute.h
index 766340e..b19dec6 100644
--- a/droute/droute.h
+++ b/droute/droute.h
@@ -97,8 +97,17 @@ void
 droute_path_register (DRoutePath *path, DBusConnection *bus);
 
 void
+droute_path_unregister (DRoutePath *path, DBusConnection *bus);
+
+void
 droute_context_register (DRouteContext *cnx, DBusConnection *bus);
 
 void
+droute_context_unregister (DRouteContext *cnx, DBusConnection *bus);
+
+void
 droute_intercept_dbus (DBusConnection *connection);
+
+void
+droute_unintercept_dbus (DBusConnection *connection);
 #endif /* _DROUTE_H */



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