Merge lp:~chrisccoulson/libdbusmenu/memory-fixes into lp:libdbusmenu/0.5

Proposed by Chris Coulson
Status: Merged
Merged at revision: 220
Proposed branch: lp:~chrisccoulson/libdbusmenu/memory-fixes
Merge into: lp:libdbusmenu/0.5
Diff against target: 131 lines (+40/-26)
1 file modified
libdbusmenu-gtk/parser.c (+40/-26)
To merge this branch: bzr merge lp:~chrisccoulson/libdbusmenu/memory-fixes
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+50934@code.launchpad.net

Description of the change

Various memory error fixes:
- Don't call g_object_add_weak_pointer multiple times on GtkMenuShell's
- Ensure we always clean up weak pointers to avoid invalid writes when
  objects are destroyed
- If a GtkWidget is destroyed before it's DbusmenuMenuitem, don't try to access
  it with g_object_steal_data

To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

  review approve

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libdbusmenu-gtk/parser.c'
--- libdbusmenu-gtk/parser.c 2011-02-21 15:54:31 +0000
+++ libdbusmenu-gtk/parser.c 2011-02-23 14:40:15 +0000
@@ -109,45 +109,58 @@
109 return recurse.parent;109 return recurse.parent;
110}110}
111111
112/* Called when the dbusmenu item that we're keeping around
113 is finalized */
114static void112static void
115dbusmenu_cache_freed (gpointer data, GObject * obj)113parse_data_free (gpointer data)
116{114{
117 /* If the dbusmenu item is killed we don't need to remove115 ParserData *pdata = (ParserData *)data;
118 the weak ref as well. */
119 g_object_steal_data(G_OBJECT(data), CACHED_MENUITEM);
120
121 ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(obj), PARSER_DATA);
122116
123 if (pdata != NULL && pdata->label != NULL) {117 if (pdata != NULL && pdata->label != NULL) {
124 g_signal_handlers_disconnect_by_func(pdata->label, G_CALLBACK(label_notify_cb), obj);118 g_signal_handlers_disconnect_matched(pdata->label, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
119 0, 0, NULL, G_CALLBACK(label_notify_cb), NULL);
125 g_object_remove_weak_pointer(G_OBJECT(pdata->label), (gpointer*)&pdata->label);120 g_object_remove_weak_pointer(G_OBJECT(pdata->label), (gpointer*)&pdata->label);
126 }121 }
127122
128 if (pdata != NULL && pdata->action != NULL) {123 if (pdata != NULL && pdata->action != NULL) {
129 g_signal_handlers_disconnect_by_func(pdata->action, G_CALLBACK(action_notify_cb), obj);124 g_signal_handlers_disconnect_matched(pdata->action, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
125 0, 0, NULL, G_CALLBACK(action_notify_cb), NULL);
130 g_object_remove_weak_pointer(G_OBJECT(pdata->action), (gpointer*)&pdata->action);126 g_object_remove_weak_pointer(G_OBJECT(pdata->action), (gpointer*)&pdata->action);
131 }127 }
132128
133 if (pdata != NULL && pdata->widget != NULL) {129 if (pdata != NULL && pdata->widget != NULL) {
134 g_signal_handlers_disconnect_by_func(pdata->widget, G_CALLBACK(widget_notify_cb), obj);130 g_signal_handlers_disconnect_matched(pdata->widget, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
131 0, 0, NULL, G_CALLBACK(widget_notify_cb), NULL);
135 g_object_remove_weak_pointer(G_OBJECT(pdata->widget), (gpointer*)&pdata->widget);132 g_object_remove_weak_pointer(G_OBJECT(pdata->widget), (gpointer*)&pdata->widget);
136 }133 }
137134
138 if (pdata != NULL && pdata->shell != NULL) {135 if (pdata != NULL && pdata->shell != NULL) {
139 g_signal_handlers_disconnect_by_func(pdata->shell, G_CALLBACK(child_added_cb), obj);136 g_signal_handlers_disconnect_matched(pdata->shell, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
137 0, 0, NULL, G_CALLBACK(child_added_cb), NULL);
140 g_object_remove_weak_pointer(G_OBJECT(pdata->shell), (gpointer*)&pdata->shell);138 g_object_remove_weak_pointer(G_OBJECT(pdata->shell), (gpointer*)&pdata->shell);
141 }139 }
142140
143 if (pdata != NULL && pdata->image != NULL) {141 if (pdata != NULL && pdata->image != NULL) {
144 g_signal_handlers_disconnect_by_func(pdata->image, G_CALLBACK(image_notify_cb), obj);142 g_signal_handlers_disconnect_matched(pdata->image, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
143 0, 0, NULL, G_CALLBACK(image_notify_cb), NULL);
145 g_object_remove_weak_pointer(G_OBJECT(pdata->image), (gpointer*)&pdata->image);144 g_object_remove_weak_pointer(G_OBJECT(pdata->image), (gpointer*)&pdata->image);
146 }145 }
147146
147 g_free(pdata);
148
148 return;149 return;
149}150}
150151
152/* Called when the dbusmenu item that we're keeping around
153 is finalized */
154static void
155dbusmenu_item_freed (gpointer data, GObject * obj)
156{
157 ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(obj), PARSER_DATA);
158
159 if (pdata != NULL && pdata->widget != NULL) {
160 g_object_steal_data(G_OBJECT(pdata->widget), CACHED_MENUITEM);
161 }
162}
163
151/* Called if we replace the cache on the object with a new164/* Called if we replace the cache on the object with a new
152 dbusmenu menuitem */165 dbusmenu menuitem */
153static void166static void
@@ -198,10 +211,13 @@
198 DbusmenuMenuitem * item = dbusmenu_menuitem_new();211 DbusmenuMenuitem * item = dbusmenu_menuitem_new();
199212
200 ParserData *pdata = g_new0 (ParserData, 1);213 ParserData *pdata = g_new0 (ParserData, 1);
201 g_object_set_data_full(G_OBJECT(item), PARSER_DATA, pdata, g_free);214 g_object_set_data_full(G_OBJECT(item), PARSER_DATA, pdata, parse_data_free);
202215
203 g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, item, object_cache_freed);216 g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, item, object_cache_freed);
204 g_object_weak_ref(G_OBJECT(item), dbusmenu_cache_freed, widget);217 g_object_weak_ref(G_OBJECT(item), dbusmenu_item_freed, NULL);
218
219 pdata->widget = widget;
220 g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->widget);
205221
206 return item;222 return item;
207}223}
@@ -237,17 +253,17 @@
237253
238 if (recurse->parent == NULL) {254 if (recurse->parent == NULL) {
239 recurse->parent = new_menuitem(widget);255 recurse->parent = new_menuitem(widget);
256
257 ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(recurse->parent), PARSER_DATA);
258
259 pdata->shell = widget;
260 g_signal_connect (G_OBJECT (widget),
261 "child-added",
262 G_CALLBACK (child_added_cb),
263 recurse->parent);
264 g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->shell);
240 }265 }
241266
242 ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(recurse->parent), PARSER_DATA);
243
244 pdata->shell = widget;
245 g_signal_connect (G_OBJECT (widget),
246 "child-added",
247 G_CALLBACK (child_added_cb),
248 recurse->parent);
249 g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->shell);
250
251 gtk_container_foreach (GTK_CONTAINER (widget),267 gtk_container_foreach (GTK_CONTAINER (widget),
252 (GtkCallback)parse_menu_structure_helper,268 (GtkCallback)parse_menu_structure_helper,
253 recurse);269 recurse);
@@ -472,12 +488,10 @@
472 DBUSMENU_MENUITEM_PROP_ENABLED,488 DBUSMENU_MENUITEM_PROP_ENABLED,
473 sensitive);489 sensitive);
474490
475 pdata->widget = widget;
476 g_signal_connect (widget,491 g_signal_connect (widget,
477 "notify",492 "notify",
478 G_CALLBACK (widget_notify_cb),493 G_CALLBACK (widget_notify_cb),
479 mi);494 mi);
480 g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->widget);
481495
482 return mi;496 return mi;
483 }497 }

Subscribers

People subscribed via source and target branches