Merge lp:~3v1n0/bamf/factory-ref-rework into lp:bamf

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Ted Gould
Approved revision: 569
Merged at revision: 547
Proposed branch: lp:~3v1n0/bamf/factory-ref-rework
Merge into: lp:bamf
Diff against target: 451 lines (+164/-87)
4 files modified
debian/changelog (+9/-10)
lib/libbamf/bamf-factory.c (+135/-75)
lib/libbamf/bamf-view.c (+19/-1)
src/bamf-matcher.c (+1/-1)
To merge this branch: bzr merge lp:~3v1n0/bamf/factory-ref-rework
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Ted Gould (community) Approve
Review via email: mp+169193@code.launchpad.net

Commit message

BamfFactory: fix references of allocated/closed views; improve re-matching of views

Now the ownership of the open views is in the hash-table, closed views must be owned
by clients (if they want to). The factory also tracks the allocated views until they
don't get destroyed to re-use them if possible.

Description of the change

The factory was owning the views it allocated in the bad way, and was re-opening closed views without taking the ownership of them.

Now the ownership of the open views is in the hash-table, closed views must be owned by clients (if they want to). The factory also tracks the allocated views until they don't get destroyed to re-use them if possible.

Added closed view re-matching by application name (only if the name is unique).

When the bamfdaemon is killed / stopped now all the views are set as closed, so that they can be correctly re-matched.

You can use this test-binary to check what happens in libbamf: http://pastebin.ubuntu.com/5761483/

Together with a script like
count=0; while [ $count -lt 20 ]; do xclock& sleep 0.3 && kill $(pidof xclock); count=$((count+1)); done

Can give some informations..

To post a comment you must log in.
lp:~3v1n0/bamf/factory-ref-rework updated
569. By Marco Trevisan (Treviño)

BamfFactory: comment wording fix

Revision history for this message
Ted Gould (ted) wrote :

Really worried about reference leaks there, but I can't find any. You should probably consider in the future adding some tests that make sure you're not keeping any internal references of objects.

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

> Really worried about reference leaks there, but I can't find any. You should
> probably consider in the future adding some tests that make sure you're not
> keeping any internal references of objects.

Yes, true... Tests are something I must work on, but bamf was mostly untested since few months ago, so slowly adding them...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andrea Azzarone (azzar1) wrote :

LGTM too.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2013-06-11 14:24:57 +0000
+++ debian/changelog 2013-06-13 13:28:30 +0000
@@ -1,5 +1,6 @@
1bamf (0.5.0) UNRELEASED; urgency=low1bamf (0.5.0) UNRELEASED; urgency=low
22
3 [ Marco Trevisan (Treviño) ]
3 * New upstream release, bumping debian version to 0.5.04 * New upstream release, bumping debian version to 0.5.0
4 * LibBamfPrivate: add new private library to share code between client5 * LibBamfPrivate: add new private library to share code between client
5 and daemon.6 and daemon.
@@ -7,16 +8,14 @@
7 allows to have correct values and signals when they get updated.8 allows to have correct values and signals when they get updated.
8 Deprecating related dbus methods/signals.9 Deprecating related dbus methods/signals.
9 * debian/control:10 * debian/control:
10 - don't build-depend anymore on libdbus-glib-1-dev11 - don't build-depend anymore on libdbus-glib-1-dev
1112
12 -- Marco Trevisan (Treviño) <marco@ubuntu.com> Wed, 05 Jun 2013 14:00:27 +020013 [ Jeremy Bicha ]
1314 * debian/control:
14bamf (0.4.0daily13.06.07-0ubuntu2) UNRELEASED; urgency=low15 - Have libbamf3-dev depend on gir1.2-bamf-3
1516 - Drop explicit build-depends on gir1.2-glib-2.0
16 * Have libbamf3-dev depend on gir1.2-bamf-317
17 * Drop explicit build-depends on gir1.2-glib-2.0 18 -- Marco Trevisan (Treviño) <marco@ubuntu.com> Wed, 12 Jun 2013 14:30:03 +0200
18
19 -- Jeremy Bicha <jbicha@ubuntu.com> Mon, 10 Jun 2013 14:28:12 -0400
2019
21bamf (0.4.0daily13.06.07-0ubuntu1) saucy; urgency=low20bamf (0.4.0daily13.06.07-0ubuntu1) saucy; urgency=low
2221
2322
=== modified file 'lib/libbamf/bamf-factory.c'
--- lib/libbamf/bamf-factory.c 2013-06-10 16:58:39 +0000
+++ lib/libbamf/bamf-factory.c 2013-06-13 13:28:30 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2010-2012 Canonical Ltd.2 * Copyright 2010-2013 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of either or both of the following licenses:5 * under the terms of either or both of the following licenses:
@@ -21,7 +21,7 @@
21 *21 *
22 * Authored by: Jason Smith <jason.smith@canonical.com>22 * Authored by: Jason Smith <jason.smith@canonical.com>
23 * Neil Jagdish Patel <neil.patel@canonical.com>23 * Neil Jagdish Patel <neil.patel@canonical.com>
24 * Marco Trevisan (Treviño) <3v1n0@ubuntu.com>24 * Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
25 *25 *
26 */26 */
27/**27/**
@@ -49,40 +49,57 @@
49{49{
50 GHashTable *open_views;50 GHashTable *open_views;
51 GList *local_views;51 GList *local_views;
52 GList *registered_views;52 GList *allocated_views;
53};53};
5454
55static BamfFactory *static_factory = NULL;55static BamfFactory *static_factory = NULL;
5656
57static void on_view_weak_unref (BamfFactory *self, BamfView *view_was_here);
58
57static void59static void
58bamf_factory_dispose (GObject *object)60bamf_factory_dispose (GObject *object)
59{61{
60 BamfFactory *self = (BamfFactory *) object;62 GList *l, *next;
6163 BamfFactory *self = BAMF_FACTORY (object);
62 if (self->priv->open_views)64
63 {65 if (self->priv->allocated_views)
64 g_hash_table_destroy (self->priv->open_views);66 {
65 self->priv->open_views = NULL;67 for (l = self->priv->allocated_views, next = NULL; l; l = next)
66 }68 {
6769 g_object_weak_unref (G_OBJECT (l->data), (GWeakNotify) on_view_weak_unref, self);
68 if (self->priv->registered_views)70 next = l->next;
69 {71 g_list_free1 (l);
70 g_list_free (self->priv->registered_views);72 }
71 self->priv->registered_views = NULL;73
74 self->priv->allocated_views = NULL;
72 }75 }
7376
74 if (self->priv->local_views)77 if (self->priv->local_views)
75 {78 {
76 g_list_free_full (self->priv->local_views, g_object_unref);79 g_list_free (self->priv->local_views);
77 self->priv->local_views = NULL;80 self->priv->local_views = NULL;
78 }81 }
7982
83 if (self->priv->open_views)
84 {
85 g_hash_table_remove_all (self->priv->open_views);
86 self->priv->open_views = NULL;
87 }
88
80 G_OBJECT_CLASS (bamf_factory_parent_class)->dispose (object);89 G_OBJECT_CLASS (bamf_factory_parent_class)->dispose (object);
81}90}
8291
83static void92static void
84bamf_factory_finalize (GObject *object)93bamf_factory_finalize (GObject *object)
85{94{
95 BamfFactory *self = BAMF_FACTORY (object);
96
97 if (self->priv->open_views)
98 {
99 g_hash_table_destroy (self->priv->open_views);
100 self->priv->open_views = NULL;
101 }
102
86 static_factory = NULL;103 static_factory = NULL;
87104
88 G_OBJECT_CLASS (bamf_factory_parent_class)->finalize (object);105 G_OBJECT_CLASS (bamf_factory_parent_class)->finalize (object);
@@ -103,62 +120,75 @@
103static void120static void
104bamf_factory_init (BamfFactory *self)121bamf_factory_init (BamfFactory *self)
105{122{
106 BamfFactoryPrivate *priv;123 self->priv = BAMF_FACTORY_GET_PRIVATE (self);
107124 self->priv->open_views = g_hash_table_new_full (g_str_hash, g_str_equal,
108 priv = self->priv = BAMF_FACTORY_GET_PRIVATE (self);125 g_free, g_object_unref);
109
110 priv->open_views = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
111}126}
112127
113static void128static void
114on_view_closed (BamfView *view, BamfFactory *self)129on_view_closed (BamfView *view, BamfFactory *self)
115{130{
116 const char *path;131 const char *path;
117132 gboolean removed;
118 g_return_if_fail (BAMF_IS_VIEW (view));133
119134 removed = FALSE;
120 path = _bamf_view_get_path (view);135 path = _bamf_view_get_path (view);
121136
137 g_signal_handlers_disconnect_by_func (view, on_view_closed, self);
138
122 if (path)139 if (path)
123 g_hash_table_remove (self->priv->open_views, path);140 {
124141 removed = g_hash_table_remove (self->priv->open_views, path);
125 g_object_unref (view);142 }
126}143
127144 if (G_UNLIKELY (!removed))
128static void145 {
129on_view_weak_unref (BamfFactory *self, BamfView *view)146 /* Unlikely to happen, but who knows... */
130{147 GHashTableIter iter;
131 GHashTableIter iter;148 gpointer value;
132 gpointer key, value;149
133150 g_hash_table_iter_init (&iter, self->priv->open_views);
134 g_return_if_fail (BAMF_IS_FACTORY (self));151 while (g_hash_table_iter_next (&iter, NULL, &value))
135
136 self->priv->local_views = g_list_remove (self->priv->local_views, view);
137 self->priv->registered_views = g_list_remove (self->priv->registered_views, view);
138
139 g_hash_table_iter_init (&iter, self->priv->open_views);
140 while (g_hash_table_iter_next (&iter, &key, &value))
141 {
142 if (value == view)
143 {152 {
144 g_hash_table_iter_remove (&iter);153 if (value == view)
145 break;154 {
155 g_hash_table_iter_remove (&iter);
156 removed = TRUE;
157 break;
158 }
146 }159 }
147 }160 }
148}161}
149162
150static void163static void
164on_view_weak_unref (BamfFactory *self, BamfView *view_was_here)
165{
166 self->priv->local_views = g_list_remove (self->priv->local_views, view_was_here);
167 self->priv->allocated_views = g_list_remove (self->priv->allocated_views, view_was_here);
168}
169
170static void
171bamf_factory_track_view (BamfFactory *self, BamfView *view)
172{
173 g_return_if_fail (BAMF_IS_VIEW (view));
174
175 if (g_list_find (self->priv->allocated_views, view))
176 return;
177
178 g_object_weak_ref (G_OBJECT (view), (GWeakNotify) on_view_weak_unref, self);
179 self->priv->allocated_views = g_list_prepend (self->priv->allocated_views, view);
180}
181
182static void
151bamf_factory_register_view (BamfFactory *self, BamfView *view, const char *path)183bamf_factory_register_view (BamfFactory *self, BamfView *view, const char *path)
152{184{
185 g_return_if_fail (BAMF_IS_VIEW (view));
186 g_return_if_fail (path != NULL);
187
188 g_object_ref_sink (view);
153 g_hash_table_insert (self->priv->open_views, g_strdup (path), view);189 g_hash_table_insert (self->priv->open_views, g_strdup (path), view);
154190 g_signal_connect_after (G_OBJECT (view), BAMF_VIEW_SIGNAL_CLOSED,
155 if (g_list_find (self->priv->registered_views, view))191 G_CALLBACK (on_view_closed), self);
156 return;
157
158 g_signal_connect_after (G_OBJECT (view), "closed", (GCallback) on_view_closed, self);
159 g_object_weak_ref (G_OBJECT (view), (GWeakNotify) on_view_weak_unref, self);
160
161 self->priv->registered_views = g_list_prepend (self->priv->registered_views, view);
162}192}
163193
164BamfApplication *194BamfApplication *
@@ -188,9 +218,11 @@
188 {218 {
189 /* delay registration until match time */219 /* delay registration until match time */
190 result = bamf_application_new_favorite (path);220 result = bamf_application_new_favorite (path);
191 if (result && !g_list_find (factory->priv->local_views, result))221
222 if (BAMF_IS_APPLICATION (result))
192 {223 {
193 factory->priv->local_views = g_list_prepend (factory->priv->local_views, result);224 factory->priv->local_views = g_list_prepend (factory->priv->local_views, result);
225 bamf_factory_track_view (factory, BAMF_VIEW (result));
194 }226 }
195 }227 }
196228
@@ -249,7 +281,6 @@
249 BamfView *view;281 BamfView *view;
250 BamfDBusItemView *vproxy;282 BamfDBusItemView *vproxy;
251 GList *l;283 GList *l;
252 gboolean created = FALSE;
253284
254 g_return_val_if_fail (BAMF_IS_FACTORY (factory), NULL);285 g_return_val_if_fail (BAMF_IS_FACTORY (factory), NULL);
255286
@@ -298,20 +329,25 @@
298 break;329 break;
299 }330 }
300331
301 created = TRUE;
302 BamfView *matched_view = NULL;332 BamfView *matched_view = NULL;
303333
334 /* handle case where another allocated (but closed) view exists and the new
335 * one matches it, so that we can reuse it. */
304 if (BAMF_IS_APPLICATION (view))336 if (BAMF_IS_APPLICATION (view))
305 {337 {
306 /* handle case where another living view exists and the new one matches it */
307 const char *local_desktop_file = bamf_application_get_desktop_file (BAMF_APPLICATION (view));338 const char *local_desktop_file = bamf_application_get_desktop_file (BAMF_APPLICATION (view));
308 GList *local_children = _bamf_application_get_cached_xids (BAMF_APPLICATION (view));339 GList *local_children = _bamf_application_get_cached_xids (BAMF_APPLICATION (view));
340 char *local_name = bamf_view_get_name (view);
341 gboolean matched_by_name = FALSE;
309342
310 for (l = factory->priv->local_views; l; l = l->next)343 for (l = factory->priv->allocated_views; l; l = l->next)
311 {344 {
312 if (!BAMF_IS_APPLICATION (l->data))345 if (!BAMF_IS_APPLICATION (l->data))
313 continue;346 continue;
314347
348 if (!bamf_view_is_closed (l->data))
349 continue;
350
315 BamfView *list_view = BAMF_VIEW (l->data);351 BamfView *list_view = BAMF_VIEW (l->data);
316 BamfApplication *list_app = BAMF_APPLICATION (l->data);352 BamfApplication *list_app = BAMF_APPLICATION (l->data);
317353
@@ -326,7 +362,7 @@
326362
327 /* If the primary search doesn't give out any result, we fallback363 /* If the primary search doesn't give out any result, we fallback
328 * to children window comparison */364 * to children window comparison */
329 if (!list_desktop_file && !matched_view)365 if (!list_desktop_file)
330 {366 {
331 GList *list_children, *ll;367 GList *list_children, *ll;
332 list_children = _bamf_application_get_cached_xids (list_app);368 list_children = _bamf_application_get_cached_xids (list_app);
@@ -341,18 +377,45 @@
341 break;377 break;
342 }378 }
343 }379 }
380
381 if ((!matched_view || matched_by_name) && local_name && local_name[0] != '\0')
382 {
383 char *list_name = bamf_view_get_name (list_view);
384 if (g_strcmp0 (local_name, list_name) == 0)
385 {
386 if (!matched_by_name)
387 {
388 matched_view = list_view;
389 matched_by_name = TRUE;
390 }
391 else
392 {
393 /* We have already matched an app by its name, this
394 * means that there are two apps with the same name.
395 * It's safer to ignore both, then. */
396 matched_view = NULL;
397 }
398 }
399
400 g_free (list_name);
401 }
344 }402 }
345 }403 }
404
405 g_free (local_name);
346 }406 }
347 else if (BAMF_IS_WINDOW (view))407 else if (BAMF_IS_WINDOW (view))
348 {408 {
349 guint32 local_xid = bamf_window_get_xid (BAMF_WINDOW (view));409 guint32 local_xid = bamf_window_get_xid (BAMF_WINDOW (view));
350410
351 for (l = factory->priv->local_views; l; l = l->next)411 for (l = factory->priv->allocated_views; l; l = l->next)
352 {412 {
353 if (!BAMF_IS_WINDOW (l->data))413 if (!BAMF_IS_WINDOW (l->data))
354 continue;414 continue;
355415
416 if (!bamf_view_is_closed (l->data))
417 continue;
418
356 BamfView *list_view = BAMF_VIEW (l->data);419 BamfView *list_view = BAMF_VIEW (l->data);
357 BamfWindow *list_win = BAMF_WINDOW (l->data);420 BamfWindow *list_win = BAMF_WINDOW (l->data);
358421
@@ -369,27 +432,24 @@
369432
370 if (matched_view)433 if (matched_view)
371 {434 {
372 created = FALSE;
373
374 if (view)435 if (view)
375 g_object_unref (view);436 {
437 /* We don't need anymore the view we've just created, let's forget it */
438 g_object_unref (view);
439 }
376440
441 /* If we are here, we're pretty sure that the view is not in the
442 * open_views, hash-table (since it has been closed) so we can safely
443 * re-register it here again. */
377 view = matched_view;444 view = matched_view;
378 _bamf_view_set_path (view, path);445 _bamf_view_set_path (view, path);
379446 bamf_factory_register_view (factory, view, path);
380 // FIXME: this is shouldn't be needed
381 g_object_ref_sink (view);
382 }447 }
383448 else if (view)
384 if (view)
385 {449 {
450 /* It's the first time we register this view, we also have to track it, then */
451 bamf_factory_track_view (factory, view);
386 bamf_factory_register_view (factory, view, path);452 bamf_factory_register_view (factory, view, path);
387
388 if (created)
389 {
390 g_object_ref_sink (view);
391 factory->priv->local_views = g_list_prepend (factory->priv->local_views, view);
392 }
393 }453 }
394454
395 return view;455 return view;
396456
=== modified file 'lib/libbamf/bamf-view.c'
--- lib/libbamf/bamf-view.c 2013-06-11 13:00:51 +0000
+++ lib/libbamf/bamf-view.c 2013-06-13 13:28:30 +0000
@@ -506,6 +506,21 @@
506}506}
507507
508static void508static void
509bamf_view_on_name_owner_changed (BamfDBusItemView *proxy, GParamSpec *param, BamfView *self)
510{
511 /* This is called when the bamfdaemon is killed / started */
512 gchar *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy));
513
514 if (!name_owner)
515 {
516 _bamf_view_set_closed (self, TRUE);
517 g_signal_emit (G_OBJECT (self), view_signals[CLOSED], 0);
518 }
519
520 g_free (name_owner);
521}
522
523static void
509bamf_view_on_active_changed (BamfDBusItemView *proxy, GParamSpec *param, BamfView *self)524bamf_view_on_active_changed (BamfDBusItemView *proxy, GParamSpec *param, BamfView *self)
510{525{
511 gboolean active = _bamf_dbus_item_view_get_active (proxy);526 gboolean active = _bamf_dbus_item_view_get_active (proxy);
@@ -768,6 +783,9 @@
768 _bamf_view_reset_flags (view);783 _bamf_view_reset_flags (view);
769 g_object_notify_by_pspec (G_OBJECT (view), properties[PROP_PATH]);784 g_object_notify_by_pspec (G_OBJECT (view), properties[PROP_PATH]);
770785
786 g_signal_connect (priv->proxy, "notify::g-name-owner",
787 G_CALLBACK (bamf_view_on_name_owner_changed), view);
788
771 g_signal_connect (priv->proxy, "notify::active",789 g_signal_connect (priv->proxy, "notify::active",
772 G_CALLBACK (bamf_view_on_active_changed), view);790 G_CALLBACK (bamf_view_on_active_changed), view);
773791
@@ -835,7 +853,7 @@
835 view_signals [CLOSED] =853 view_signals [CLOSED] =
836 g_signal_new (BAMF_VIEW_SIGNAL_CLOSED,854 g_signal_new (BAMF_VIEW_SIGNAL_CLOSED,
837 G_OBJECT_CLASS_TYPE (klass),855 G_OBJECT_CLASS_TYPE (klass),
838 G_SIGNAL_RUN_FIRST,856 G_SIGNAL_RUN_LAST,
839 G_STRUCT_OFFSET (BamfViewClass, closed),857 G_STRUCT_OFFSET (BamfViewClass, closed),
840 NULL, NULL,858 NULL, NULL,
841 g_cclosure_marshal_VOID__VOID,859 g_cclosure_marshal_VOID__VOID,
842860
=== modified file 'src/bamf-matcher.c'
--- src/bamf-matcher.c 2013-06-11 13:18:00 +0000
+++ src/bamf-matcher.c 2013-06-13 13:28:30 +0000
@@ -2821,6 +2821,7 @@
2821 return TRUE;2821 return TRUE;
2822}2822}
28232823
2824#ifdef HAVE_WEBAPPS
2824static gboolean2825static gboolean
2825bamf_matcher_has_tab_with_parent_xid (BamfMatcher *matcher, guint64 xid)2826bamf_matcher_has_tab_with_parent_xid (BamfMatcher *matcher, guint64 xid)
2826{2827{
@@ -2839,7 +2840,6 @@
2839 return FALSE;2840 return FALSE;
2840}2841}
28412842
2842#ifdef HAVE_WEBAPPS
2843static void2843static void
2844on_webapp_child_added (BamfView *application,2844on_webapp_child_added (BamfView *application,
2845 BamfView *child,2845 BamfView *child,

Subscribers

People subscribed via source and target branches