Merge lp:~mhr3/libunity/fix-1199715 into lp:libunity

Proposed by Michal Hruby
Status: Merged
Approved by: Paweł Stołowski
Approved revision: 294
Merged at revision: 294
Proposed branch: lp:~mhr3/libunity/fix-1199715
Merge into: lp:libunity
Diff against target: 288 lines (+130/-16)
7 files modified
protocol/protocol-scope-interface.vala (+2/-1)
src/unity-aggregator-scope-private.vala (+13/-1)
src/unity-deprecated-scope-impl.vala (+2/-1)
src/unity-scope-channel.vala (+70/-9)
src/unity-scope-dbus-impl.vala (+13/-1)
src/unity-scope-tracker.vala (+29/-2)
tools/unity-tool-ui.vala (+1/-1)
To merge this branch: bzr merge lp:~mhr3/libunity/fix-1199715
Reviewer Review Type Date Requested Status
Paweł Stołowski (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+187172@code.launchpad.net

Commit message

Auto-close channels when their owner disappears from the bus

Description of the change

Auto-close channels when their owner disappears from the bus. Also ensure that the tracker class that manages subscopes for aggregator scopes closes the subscopes' channels when the master channel closes.

Also includes code that ensures that there are no reference cycles in the ScopeChannel class.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Paweł Stołowski (stolowski) wrote :

Yay, no more home scope crashes with this fix :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'protocol/protocol-scope-interface.vala'
2--- protocol/protocol-scope-interface.vala 2013-08-26 09:15:14 +0000
3+++ protocol/protocol-scope-interface.vala 2013-09-24 09:09:27 +0000
4@@ -131,7 +131,8 @@
5 uint channel_type,
6 HashTable<string, Variant> hints,
7 Cancellable? cancellable = null,
8- out HashTable<string, Variant> out_hints) throws IOError;
9+ out HashTable<string, Variant> out_hints,
10+ BusName? sender = null) throws IOError;
11
12 public abstract async void close_channel (
13 string channel_id,
14
15=== modified file 'src/unity-aggregator-scope-private.vala'
16--- src/unity-aggregator-scope-private.vala 2013-08-19 12:00:49 +0000
17+++ src/unity-aggregator-scope-private.vala 2013-09-24 09:09:27 +0000
18@@ -593,6 +593,12 @@
19 }
20 }
21
22+ private void channel_owner_lost (ScopeChannel channel)
23+ {
24+ var empty = new HashTable<string, Variant> (str_hash, str_equal);
25+ close_channel.begin (channel.id, empty, null);
26+ }
27+
28 private void on_proxy_categories_changed (string scope_id, ScopeProxy proxy)
29 {
30 if (category_merger is CategoryMergerByField)
31@@ -1395,7 +1401,8 @@
32 uint channel_type,
33 HashTable<string, Variant> hints,
34 GLib.Cancellable? cancellable,
35- out HashTable<string, Variant> out_hints) throws IOError
36+ out HashTable<string, Variant> out_hints,
37+ BusName? sender = null) throws IOError
38 {
39 Unity.AggregatorScope aggscope = owner as Unity.AggregatorScope;
40
41@@ -1435,6 +1442,11 @@
42 if (channel.transfer_model != null)
43 {
44 yield Internal.Utils.wait_for_model_synchronization (channel.transfer_model);
45+ if (sender != null)
46+ {
47+ channel.watch_owner (_dbus_connection, sender);
48+ channel.owner_lost.connect (this.channel_owner_lost);
49+ }
50 }
51
52 _channels[channel.id] = channel;
53
54=== modified file 'src/unity-deprecated-scope-impl.vala'
55--- src/unity-deprecated-scope-impl.vala 2013-07-24 13:15:22 +0000
56+++ src/unity-deprecated-scope-impl.vala 2013-09-24 09:09:27 +0000
57@@ -608,7 +608,8 @@
58 uint channel_type,
59 HashTable<string, Variant> hints,
60 GLib.Cancellable? cancellable,
61- out HashTable<string, Variant> out_hints) throws IOError
62+ out HashTable<string, Variant> out_hints,
63+ BusName? sender) throws IOError
64 {
65 ChannelFlags flags = ChannelFlags.from_hints (hints);
66 var channel = new ScopeChannel ((ChannelType) channel_type);
67
68=== modified file 'src/unity-scope-channel.vala'
69--- src/unity-scope-channel.vala 2013-07-15 09:56:14 +0000
70+++ src/unity-scope-channel.vala 2013-09-24 09:09:27 +0000
71@@ -55,6 +55,9 @@
72
73 private string last_push_search_string;
74 private GLib.List<Dee.SerializableModel> pushed_models = new GLib.List<Dee.SerializableModel> ();
75+ private OwnerWatcher? watcher;
76+
77+ public signal void owner_lost ();
78
79 public ScopeChannel (ChannelType channel_type_)
80 {
81@@ -64,6 +67,14 @@
82 model_lock = new Utils.AsyncMutex ();
83 }
84
85+ ~ScopeChannel ()
86+ {
87+ if (watcher != null)
88+ {
89+ watcher.unwatch ();
90+ }
91+ }
92+
93 public SearchType get_search_type ()
94 {
95 SearchType search_type = channel_type == ChannelType.DEFAULT ?
96@@ -71,24 +82,19 @@
97 return search_type;
98 }
99
100- private Dee.SerializableModel create_backend_model (
101- HashTable<string, string> metadata_schema,
102- bool no_filtering,
103- out Dee.SerializableModel real_backend)
104+ private static Dee.SerializableModel create_filter_model (
105+ Dee.Model backend, HashTable<string, string> metadata_schema)
106 {
107- var backend = new Dee.SequenceModel ();
108- real_backend = backend;
109- if (no_filtering || metadata_schema.size () == 0) return backend;
110-
111 var types = new HashTable<string, VariantType> (str_hash, str_equal);
112 metadata_schema.for_each ((field, schema) =>
113 {
114 types[field] = new VariantType (schema);
115 });
116+
117 var model = new Dee.FilterModel (
118 backend, Dee.Filter.new (
119 () => {}, // no need for map func, the model is empty on creation
120- (orig_model, iter, filter_model) =>
121+ (orig_model, iter, filter_model) =>
122 {
123 // check that the row contains all required metadata
124 var metadata = orig_model.get_value (iter, METADATA_COLUMN);
125@@ -112,6 +118,18 @@
126 return model;
127 }
128
129+ private Dee.SerializableModel create_backend_model (
130+ HashTable<string, string> metadata_schema,
131+ bool no_filtering,
132+ out Dee.SerializableModel real_backend)
133+ {
134+ var backend = new Dee.SequenceModel ();
135+ real_backend = backend;
136+ if (no_filtering || metadata_schema.size () == 0) return backend;
137+
138+ return create_filter_model (backend, metadata_schema);
139+ }
140+
141 public string create_channel (string swarm_name,
142 HashTable<string, string> metadata_schema,
143 HashTable<string, string> optional_metadata,
144@@ -277,6 +295,49 @@
145
146 return pushed_models.copy ();
147 }
148+
149+ /* Separate class to ensure we don't have reference cycles */
150+ private class OwnerWatcher
151+ {
152+ private uint owner_changed_signal_id;
153+ private unowned ScopeChannel owner_channel;
154+ private DBusConnection dbus_connection;
155+
156+ public OwnerWatcher (ScopeChannel channel, DBusConnection connection, BusName owner)
157+ {
158+ owner_channel = channel;
159+ dbus_connection = connection;
160+ owner_changed_signal_id = dbus_connection.signal_subscribe (null,
161+ "org.freedesktop.DBus", "NameOwnerChanged", null, owner,
162+ DBusSignalFlags.NONE, this.owner_changed);
163+ }
164+
165+ private void owner_changed (DBusConnection con, string sender_name,
166+ string obj_path, string ifc_name,
167+ string sig_name, Variant parameters)
168+ {
169+ string new_owner = parameters.get_child_value (2).get_string ();
170+ if (new_owner == "")
171+ {
172+ owner_channel.owner_lost ();
173+ }
174+ }
175+
176+ public void unwatch ()
177+ {
178+ if (owner_changed_signal_id != 0)
179+ {
180+ dbus_connection.signal_unsubscribe (owner_changed_signal_id);
181+ owner_changed_signal_id = 0;
182+ }
183+ }
184+ }
185+
186+ public void watch_owner (DBusConnection connection, BusName owner)
187+ {
188+ if (watcher != null) watcher.unwatch ();
189+ watcher = new OwnerWatcher (this, connection, owner);
190+ }
191 }
192
193 } /* namespace Unity.Internal */
194
195=== modified file 'src/unity-scope-dbus-impl.vala'
196--- src/unity-scope-dbus-impl.vala 2013-08-15 15:54:43 +0000
197+++ src/unity-scope-dbus-impl.vala 2013-09-24 09:09:27 +0000
198@@ -716,7 +716,8 @@
199 uint channel_type,
200 HashTable<string, Variant> hints,
201 GLib.Cancellable? cancellable,
202- out HashTable<string, Variant> out_hints) throws IOError
203+ out HashTable<string, Variant> out_hints,
204+ BusName? sender) throws IOError
205 {
206 ChannelFlags flags = ChannelFlags.from_hints (hints);
207 var channel = new ScopeChannel ((ChannelType) channel_type);
208@@ -740,6 +741,11 @@
209 if (channel.transfer_model != null)
210 {
211 yield Internal.Utils.wait_for_model_synchronization (channel.transfer_model);
212+ if (sender != null)
213+ {
214+ channel.watch_owner (_dbus_connection, sender);
215+ channel.owner_lost.connect (this.channel_owner_lost);
216+ }
217 }
218
219 _channels[channel.id] = channel;
220@@ -760,6 +766,12 @@
221 return channel;
222 }
223
224+ private void channel_owner_lost (ScopeChannel channel)
225+ {
226+ var empty = new HashTable<string, Variant> (str_hash, str_equal);
227+ close_channel.begin (channel.id, empty, null);
228+ }
229+
230 public async void close_channel (
231 string channel_id,
232 HashTable<string, Variant> hints,
233
234=== modified file 'src/unity-scope-tracker.vala'
235--- src/unity-scope-tracker.vala 2013-07-23 17:40:45 +0000
236+++ src/unity-scope-tracker.vala 2013-09-24 09:09:27 +0000
237@@ -243,9 +243,36 @@
238 synchronizer.receiver.set_qdata<Dee.Model?> (DEDUP_MODEL_QUARK, null);
239 synchronizers.remove (master_channel_id);
240 }
241- // FIXME: close child scopes' channels
242+
243+ // close child scopes' channels
244+ var channel_keys_to_close = new HashTable<string, ScopeProxy> (str_hash, str_equal);
245+ // get all channel_ids associated with this master_channel_id
246+ for (int i = 0; i < scope_proxy_arr.length; i++)
247+ {
248+ var channel_key = get_channel_key (master_channel_id, scope_proxy_arr[i]);
249+ if (channel_key in scope_channel_ids)
250+ {
251+ if (scope_channel_ids[channel_key].get_data () != null)
252+ {
253+ channel_keys_to_close[channel_key] = scope_proxy_arr[i];
254+ }
255+ }
256+ }
257+
258+ var iter = HashTableIter<string, ScopeProxy> (channel_keys_to_close);
259+ unowned string channel_key;
260+ unowned ScopeProxy proxy;
261+
262+ while (iter.next (out channel_key, out proxy))
263+ {
264+ var child_channel_id = scope_channel_ids[channel_key].get_data ();
265+ if (child_channel_id == null) continue;
266+ proxy.close_channel.begin (child_channel_id, null);
267+ scope_channel_ids.remove (channel_key);
268+ scope_models.remove (channel_key);
269+ }
270 }
271-
272+
273 private async void wait_for_seqnum (Dee.SharedModel model, uint64 seqnum)
274 throws Error
275 {
276
277=== modified file 'tools/unity-tool-ui.vala'
278--- tools/unity-tool-ui.vala 2013-03-22 11:41:02 +0000
279+++ tools/unity-tool-ui.vala 2013-09-24 09:09:27 +0000
280@@ -318,7 +318,7 @@
281 categories_row_added_cb(dee_categories_model, iter);
282
283 var is_global = search_type_global_rbutton.get_active();
284- scope_proxy.open_channel.begin(is_global ? 1 : 0, new HashTable<string, Variant>(null, null), null, (obj, res) =>
285+ scope_proxy.open_channel.begin(is_global ? 1 : 0, new HashTable<string, Variant>(null, null), null, null, (obj, res) =>
286 {
287 var proxy = obj as Protocol.ScopeService;
288 HashTable<string, Variant> hints;

Subscribers

People subscribed via source and target branches