Fixed some problems when shutting down and restarting the module
authorMike Gorse <mgorse@novell.com>
Mon, 15 Aug 2011 19:22:02 +0000 (14:22 -0500)
committerMike Gorse <mgorse@novell.com>
Mon, 15 Aug 2011 19:22:02 +0000 (14:22 -0500)
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
atk-adaptor/accessible-cache.h
atk-adaptor/accessible-leasing.c
atk-adaptor/accessible-register.c
atk-adaptor/accessible-register.h
atk-adaptor/adaptors/cache-adaptor.c
atk-adaptor/bridge.c
atk-adaptor/event.c
droute/droute.c
droute/droute.h

index ad39819..4d5cdb3 100644 (file)
@@ -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);
 }
index 1089c6f..2f5be06 100644 (file)
@@ -44,6 +44,8 @@ struct _SpiCache
   GHashTable * objects;
   GQueue *add_traversal;
   gint add_pending_idle;
+
+  guint child_added_listener;
 };
 
 struct _SpiCacheClass
index f4d0e2f..4370bff 100644 (file)
@@ -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);
 }
 
index 83c1c6d..14f256f 100644 (file)
@@ -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
index edbe3c2..5a62ebb 100644 (file)
@@ -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);
 
 /*---------------------------------------------------------------------------*/
 
index 3b5540c..e221920 100644 (file)
@@ -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------------------------------------------------------------------------*/
index bcae3b9..d049731 100644 (file)
@@ -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 =
index f5a2d2d..e940e00 100644 (file)
@@ -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)
   {
index 20c262f..9212e4d 100644 (file)
@@ -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------------------------------------------------------------------------*/
index 766340e..b19dec6 100644 (file)
@@ -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 */