Merge lp:~bregma/unity/fix-indicator-leaks into lp:unity

Proposed by Stephen M. Webb
Status: Needs review
Proposed branch: lp:~bregma/unity/fix-indicator-leaks
Merge into: lp:unity
Diff against target: 164 lines (+35/-20)
5 files modified
services/CMakeLists.txt (+1/-1)
services/panel-indicator-accessible.c (+6/-0)
services/panel-indicator-accessible.h (+1/-0)
services/panel-root-accessible.c (+12/-17)
services/panel-service.c (+15/-2)
To merge this branch: bzr merge lp:~bregma/unity/fix-indicator-leaks
Reviewer Review Type Date Requested Status
Christopher Townsend Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+187636@code.launchpad.net

Commit message

dispose of ATK objects when indicators are removed (lp: #1231222)

Description of the change

= Problem description =

A circular ref between indicator objects and their ATK counterparts cause indicators to never get disposed, which shows up as nenory leaks on unity-panel-service shutdown. This makes it very difficult to spot other memory leaks.

= The fix =

Added a signal to dispose of the ATK objects before the indicator objects are removed.

= Test coverage =

Requires a manual test for verification: run unity-panel-service with the environment variable G_MESSAGES_DEBUG=u-p-s and verify indicator refcounts are all 1 when shut down.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Christopher Townsend (townsend) wrote :

Getting a segfault in a Panel Service test:

[ RUN ] TestPanelService.ManyEmptyIndicatorObjectsAddition
Segmentation fault

review: Needs Fixing
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

 - g_object_ref (indicator);

Why removing this? That code is used only indicators that have been instantiated somewhere else (not created by the ups, and what we call custom_indicators used only for testing), so in this case we should take the ownership of the indicator as there's no warranty that the previous owner is still alive (and that's why the test crashes).

Also I think that the code
132 if (g_object_is_floating (G_OBJECT (indicator)))
133 {
134 g_object_ref_sink (G_OBJECT (indicator));
135 }

Is not needed anymore now (indicators are no more GInitiallyUnowned, and even in that case it was placed in the wrong spot :/).

Unmerged revisions

3533. By Stephen M. Webb

broke some circular refs during shutdown to reduce memory leaks reported by valgrind (lp: #1231222)

3532. By Stephen M. Webb

unity-panel-service: add debug domain

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'services/CMakeLists.txt'
--- services/CMakeLists.txt 2013-08-07 16:37:05 +0000
+++ services/CMakeLists.txt 2013-09-26 02:15:48 +0000
@@ -38,7 +38,7 @@
38set(CFLAGS38set(CFLAGS
39 ${SERVICE_DEPS_CFLAGS}39 ${SERVICE_DEPS_CFLAGS}
40 ${SERVICE_DEPS_CFLAGS_OTHER}40 ${SERVICE_DEPS_CFLAGS_OTHER}
41 "-Werror -Wall"41 "-Werror -Wall -DG_LOG_DOMAIN=\\\"u-p-s\\\""
42 )42 )
4343
44string (REPLACE ";" " " CFLAGS "${CFLAGS}")44string (REPLACE ";" " " CFLAGS "${CFLAGS}")
4545
=== modified file 'services/panel-indicator-accessible.c'
--- services/panel-indicator-accessible.c 2011-10-05 16:54:21 +0000
+++ services/panel-indicator-accessible.c 2013-09-26 02:15:48 +0000
@@ -384,3 +384,9 @@
384384
385 return state_set;385 return state_set;
386}386}
387
388IndicatorObject *
389panel_indicator_accessible_get_indicator (PanelIndicatorAccessible *pia)
390{
391 return pia->priv->indicator;
392}
387393
=== modified file 'services/panel-indicator-accessible.h'
--- services/panel-indicator-accessible.h 2011-02-08 11:50:18 +0000
+++ services/panel-indicator-accessible.h 2013-09-26 02:15:48 +0000
@@ -49,6 +49,7 @@
4949
50GType panel_indicator_accessible_get_type (void);50GType panel_indicator_accessible_get_type (void);
51AtkObject *panel_indicator_accessible_new (IndicatorObject *indicator);51AtkObject *panel_indicator_accessible_new (IndicatorObject *indicator);
52IndicatorObject *panel_indicator_accessible_get_indicator (PanelIndicatorAccessible *pia);
5253
53G_END_DECLS54G_END_DECLS
5455
5556
=== modified file 'services/panel-root-accessible.c'
--- services/panel-root-accessible.c 2012-02-25 01:41:29 +0000
+++ services/panel-root-accessible.c 2013-09-26 02:15:48 +0000
@@ -89,23 +89,26 @@
89}89}
9090
91static void91static void
92on_indicator_removed (gpointer *data, GObject *removed_indicator)92on_indicator_removed_cb (PanelService *panel_service, IndicatorObject *indicator, AtkObject *child)
93{93{
94 PanelRootAccessible *root = data[0];94 AtkObject *parent;
95 AtkObject *child = data[1];95 PanelRootAccessible *root;
9696
97 if (indicator != panel_indicator_accessible_get_indicator (PANEL_INDICATOR_ACCESSIBLE (child)))
98 return;
99
100 parent = atk_object_get_parent (child);
101 root = PANEL_ROOT_ACCESSIBLE (parent);
97 g_return_if_fail (PANEL_IS_ROOT_ACCESSIBLE (root));102 g_return_if_fail (PANEL_IS_ROOT_ACCESSIBLE (root));
98 g_return_if_fail (ATK_IS_OBJECT (child));
99103
100 gint index = g_slist_index (root->priv->a11y_children, child);104 gint index = g_slist_index (root->priv->a11y_children, child);
101 if (index >= 0)105 if (index >= 0)
102 {106 {
103 root->priv->a11y_children = g_slist_remove (root->priv->a11y_children, child);107 root->priv->a11y_children = g_slist_remove (root->priv->a11y_children, child);
104 g_signal_emit_by_name (root, "children-changed::remove", index, child);108 g_signal_emit_by_name (root, "children-changed::remove", index, child);
109 g_signal_handlers_disconnect_by_func (panel_service, on_indicator_removed_cb, child);
105 g_object_unref (child);110 g_object_unref (child);
106 }111 }
107
108 g_free (data);
109}112}
110113
111/* Implementation of AtkObject methods */114/* Implementation of AtkObject methods */
@@ -133,17 +136,9 @@
133 indicator = panel_service_get_indicator_nth (root->priv->service, i);136 indicator = panel_service_get_indicator_nth (root->priv->service, i);
134 if (INDICATOR_IS_OBJECT (indicator))137 if (INDICATOR_IS_OBJECT (indicator))
135 {138 {
136 AtkObject *child;139 AtkObject *child = panel_indicator_accessible_new (indicator);
137 gpointer *weak_data;
138140
139 child = panel_indicator_accessible_new (indicator);141 g_signal_connect (root->priv->service, "indicator-removed", G_CALLBACK (on_indicator_removed_cb), child);
140 /* FIXME: use proper signals once we support dynamic adding/removing
141 * of indicators */
142 weak_data = g_new0 (gpointer, 2);
143 weak_data[0] = root;
144 weak_data[1] = child;
145 g_object_weak_ref (G_OBJECT (indicator),
146 (GWeakNotify) on_indicator_removed, weak_data);
147142
148 atk_object_set_parent (child, accessible);143 atk_object_set_parent (child, accessible);
149 root->priv->a11y_children = g_slist_append (root->priv->a11y_children, child);144 root->priv->a11y_children = g_slist_append (root->priv->a11y_children, child);
150145
=== modified file 'services/panel-service.c'
--- services/panel-service.c 2013-09-24 00:27:02 +0000
+++ services/panel-service.c 2013-09-26 02:15:48 +0000
@@ -92,6 +92,7 @@
92 ENTRY_ACTIVATE_REQUEST,92 ENTRY_ACTIVATE_REQUEST,
93 ENTRY_SHOW_NOW_CHANGED,93 ENTRY_SHOW_NOW_CHANGED,
94 GEOMETRIES_CHANGED,94 GEOMETRIES_CHANGED,
95 INDICATOR_REMOVED,
95 INDICATORS_CLEARED,96 INDICATORS_CLEARED,
9697
97 LAST_SIGNAL98 LAST_SIGNAL
@@ -270,6 +271,14 @@
270 NULL, NULL, NULL,271 NULL, NULL, NULL,
271 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);272 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
272273
274 _service_signals[INDICATOR_REMOVED] =
275 g_signal_new ("indicator-removed",
276 G_OBJECT_CLASS_TYPE (obj_class),
277 G_SIGNAL_RUN_LAST,
278 0,
279 NULL, NULL, NULL,
280 G_TYPE_NONE, 1, G_TYPE_OBJECT);
281
273 _service_signals[INDICATORS_CLEARED] =282 _service_signals[INDICATORS_CLEARED] =
274 g_signal_new ("indicators-cleared",283 g_signal_new ("indicators-cleared",
275 G_OBJECT_CLASS_TYPE (obj_class),284 G_OBJECT_CLASS_TYPE (obj_class),
@@ -688,11 +697,16 @@
688697
689 self->priv->indicators = g_slist_remove (self->priv->indicators, indicator);698 self->priv->indicators = g_slist_remove (self->priv->indicators, indicator);
690699
700 indicator_object_set_visible (indicator, FALSE);
701
702 g_signal_emit (self, _service_signals[INDICATOR_REMOVED], 0, indicator);
703
691 if (g_object_is_floating (G_OBJECT (indicator)))704 if (g_object_is_floating (G_OBJECT (indicator)))
692 {705 {
693 g_object_ref_sink (G_OBJECT (indicator));706 g_object_ref_sink (G_OBJECT (indicator));
694 }707 }
695708
709 g_debug ("%s unreffing indicator \"%s\" (refcount is %u)", G_STRFUNC, (gchar *)g_object_get_data (G_OBJECT (indicator), "id"), G_OBJECT(indicator)->ref_count);
696 g_object_unref (G_OBJECT (indicator));710 g_object_unref (G_OBJECT (indicator));
697}711}
698712
@@ -817,7 +831,6 @@
817 g_return_if_fail (PANEL_IS_SERVICE (self));831 g_return_if_fail (PANEL_IS_SERVICE (self));
818 g_return_if_fail (INDICATOR_IS_OBJECT (indicator));832 g_return_if_fail (INDICATOR_IS_OBJECT (indicator));
819833
820 g_object_ref (indicator);
821 load_indicator (self, indicator, NULL);834 load_indicator (self, indicator, NULL);
822}835}
823836
@@ -1116,6 +1129,7 @@
1116 }1129 }
1117 g_list_free (entries);1130 g_list_free (entries);
11181131
1132 g_debug ("%s loaded indicator \"%s\"", G_STRFUNC, name);
1119 g_free (name);1133 g_free (name);
1120}1134}
11211135
@@ -1142,7 +1156,6 @@
1142 continue;1156 continue;
11431157
1144 path = g_build_filename (INDICATORDIR, name, NULL);1158 path = g_build_filename (INDICATORDIR, name, NULL);
1145 g_debug ("Loading: %s", path);
11461159
1147 object = indicator_object_new_from_file (path);1160 object = indicator_object_new_from_file (path);
1148 if (object == NULL)1161 if (object == NULL)