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
1=== modified file 'libdbusmenu-gtk/parser.c'
2--- libdbusmenu-gtk/parser.c 2011-02-21 15:54:31 +0000
3+++ libdbusmenu-gtk/parser.c 2011-02-23 14:40:15 +0000
4@@ -109,45 +109,58 @@
5 return recurse.parent;
6 }
7
8-/* Called when the dbusmenu item that we're keeping around
9- is finalized */
10 static void
11-dbusmenu_cache_freed (gpointer data, GObject * obj)
12+parse_data_free (gpointer data)
13 {
14- /* If the dbusmenu item is killed we don't need to remove
15- the weak ref as well. */
16- g_object_steal_data(G_OBJECT(data), CACHED_MENUITEM);
17-
18- ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(obj), PARSER_DATA);
19+ ParserData *pdata = (ParserData *)data;
20
21 if (pdata != NULL && pdata->label != NULL) {
22- g_signal_handlers_disconnect_by_func(pdata->label, G_CALLBACK(label_notify_cb), obj);
23+ g_signal_handlers_disconnect_matched(pdata->label, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
24+ 0, 0, NULL, G_CALLBACK(label_notify_cb), NULL);
25 g_object_remove_weak_pointer(G_OBJECT(pdata->label), (gpointer*)&pdata->label);
26 }
27
28 if (pdata != NULL && pdata->action != NULL) {
29- g_signal_handlers_disconnect_by_func(pdata->action, G_CALLBACK(action_notify_cb), obj);
30+ g_signal_handlers_disconnect_matched(pdata->action, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
31+ 0, 0, NULL, G_CALLBACK(action_notify_cb), NULL);
32 g_object_remove_weak_pointer(G_OBJECT(pdata->action), (gpointer*)&pdata->action);
33 }
34
35 if (pdata != NULL && pdata->widget != NULL) {
36- g_signal_handlers_disconnect_by_func(pdata->widget, G_CALLBACK(widget_notify_cb), obj);
37+ g_signal_handlers_disconnect_matched(pdata->widget, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
38+ 0, 0, NULL, G_CALLBACK(widget_notify_cb), NULL);
39 g_object_remove_weak_pointer(G_OBJECT(pdata->widget), (gpointer*)&pdata->widget);
40 }
41
42 if (pdata != NULL && pdata->shell != NULL) {
43- g_signal_handlers_disconnect_by_func(pdata->shell, G_CALLBACK(child_added_cb), obj);
44+ g_signal_handlers_disconnect_matched(pdata->shell, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
45+ 0, 0, NULL, G_CALLBACK(child_added_cb), NULL);
46 g_object_remove_weak_pointer(G_OBJECT(pdata->shell), (gpointer*)&pdata->shell);
47 }
48
49 if (pdata != NULL && pdata->image != NULL) {
50- g_signal_handlers_disconnect_by_func(pdata->image, G_CALLBACK(image_notify_cb), obj);
51+ g_signal_handlers_disconnect_matched(pdata->image, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
52+ 0, 0, NULL, G_CALLBACK(image_notify_cb), NULL);
53 g_object_remove_weak_pointer(G_OBJECT(pdata->image), (gpointer*)&pdata->image);
54 }
55
56+ g_free(pdata);
57+
58 return;
59 }
60
61+/* Called when the dbusmenu item that we're keeping around
62+ is finalized */
63+static void
64+dbusmenu_item_freed (gpointer data, GObject * obj)
65+{
66+ ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(obj), PARSER_DATA);
67+
68+ if (pdata != NULL && pdata->widget != NULL) {
69+ g_object_steal_data(G_OBJECT(pdata->widget), CACHED_MENUITEM);
70+ }
71+}
72+
73 /* Called if we replace the cache on the object with a new
74 dbusmenu menuitem */
75 static void
76@@ -198,10 +211,13 @@
77 DbusmenuMenuitem * item = dbusmenu_menuitem_new();
78
79 ParserData *pdata = g_new0 (ParserData, 1);
80- g_object_set_data_full(G_OBJECT(item), PARSER_DATA, pdata, g_free);
81+ g_object_set_data_full(G_OBJECT(item), PARSER_DATA, pdata, parse_data_free);
82
83 g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, item, object_cache_freed);
84- g_object_weak_ref(G_OBJECT(item), dbusmenu_cache_freed, widget);
85+ g_object_weak_ref(G_OBJECT(item), dbusmenu_item_freed, NULL);
86+
87+ pdata->widget = widget;
88+ g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->widget);
89
90 return item;
91 }
92@@ -237,17 +253,17 @@
93
94 if (recurse->parent == NULL) {
95 recurse->parent = new_menuitem(widget);
96+
97+ ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(recurse->parent), PARSER_DATA);
98+
99+ pdata->shell = widget;
100+ g_signal_connect (G_OBJECT (widget),
101+ "child-added",
102+ G_CALLBACK (child_added_cb),
103+ recurse->parent);
104+ g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->shell);
105 }
106
107- ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(recurse->parent), PARSER_DATA);
108-
109- pdata->shell = widget;
110- g_signal_connect (G_OBJECT (widget),
111- "child-added",
112- G_CALLBACK (child_added_cb),
113- recurse->parent);
114- g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->shell);
115-
116 gtk_container_foreach (GTK_CONTAINER (widget),
117 (GtkCallback)parse_menu_structure_helper,
118 recurse);
119@@ -472,12 +488,10 @@
120 DBUSMENU_MENUITEM_PROP_ENABLED,
121 sensitive);
122
123- pdata->widget = widget;
124 g_signal_connect (widget,
125 "notify",
126 G_CALLBACK (widget_notify_cb),
127 mi);
128- g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->widget);
129
130 return mi;
131 }

Subscribers

People subscribed via source and target branches