Merge lp:~thomas-voss/location-service/fix-nm-race into lp:location-service/trunk

Proposed by Thomas Voß
Status: Merged
Approved by: Thomas Voß
Approved revision: 153
Merged at revision: 148
Proposed branch: lp:~thomas-voss/location-service/fix-nm-race
Merge into: lp:location-service/trunk
Diff against target: 219 lines (+102/-60)
3 files modified
src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.cpp (+1/-2)
src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp (+97/-56)
src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h (+4/-2)
To merge this branch: bzr merge lp:~thomas-voss/location-service/fix-nm-race
Reviewer Review Type Date Requested Status
Loïc Minier Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+241090@code.launchpad.net

Commit message

Make sure that devices being added/removed by NetworkManager are handled correctly.

Description of the change

Make sure that devices being added/removed by NetworkManager are handled correctly.

To post a comment you must log in.
148. By Thomas Voß

Lock the cache when accessing it from signal handlers.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Loïc Minier (lool) wrote :

Looks good outside of not being sure about default connection handling

149. By Thomas Voß

Do not recalculate connection characteristics for every new device. Instead, rely on the established way of listening for changes to the active connection obect.

150. By Thomas Voß

Bail out if the cache already knows about the device.

151. By Thomas Voß

Add missing ;.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Loïc Minier (lool) wrote :

(Latest version still breaks HERE)

152. By Thomas Voß

Disconnect from properties changed signal on destructin, as mentioned in the TODO.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
153. By Thomas Voß

Make sure that locking is done correctly.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Loïc Minier (lool) wrote :

Hmm the locking is a bit spaghetti now; I can see why lock needs to be passed around to unlock before dispatching the updates from the on_foo() callbacks, but it does feel a bit weird to pass the lock down a callback and unlock it from there.

I guess the only way would be to queue the added/removed wifis/cells into a queue and trigger the updates once the lock is released, but that's pretty much as weird.

Anyway, tested, and seems to help with the otherwise failing test case.

Note that: a) I wasn't able to reproduce on mako + vivid, so couldn't confirm this fixed anything; b) it did help reproducible breakage on krillin from earlier revisions, but I did manage to break HERE on one boot.

So generally, this helps; I suspect there's still a race for a case.

I did witness tech=cell switching to tech=wifi on krillin when coming out of airplane mode, which was nice!

review: Approve
Revision history for this message
Thomas Voß (thomas-voss) wrote :

> Hmm the locking is a bit spaghetti now; I can see why lock needs to be passed
> around to unlock before dispatching the updates from the on_foo() callbacks,
> but it does feel a bit weird to pass the lock down a callback and unlock it
> from there.
>

The one case is technically not a callback but a functor passed for evaluation. In all other cases, the lock is created within the callback and handed down to the actual function. I do prefer this API style to naming functions *_locked(...), which is tedious and error prone.

> I guess the only way would be to queue the added/removed wifis/cells into a
> queue and trigger the updates once the lock is released, but that's pretty
> much as weird.
>
> Anyway, tested, and seems to help with the otherwise failing test case.
>
> Note that: a) I wasn't able to reproduce on mako + vivid, so couldn't confirm
> this fixed anything; b) it did help reproducible breakage on krillin from
> earlier revisions, but I did manage to break HERE on one boot.
>

> So generally, this helps; I suspect there's still a race for a case.
>
> I did witness tech=cell switching to tech=wifi on krillin when coming out of
> airplane mode, which was nice!

Thanks.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.cpp'
2--- src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.cpp 2014-10-13 15:20:56 +0000
3+++ src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.cpp 2014-11-10 20:13:24 +0000
4@@ -172,8 +172,7 @@
5
6 detail::CachedRadioCell::~CachedRadioCell()
7 {
8- // TODO(tvoss): Reenable this once we know why the modem cache gets flushed.
9- // modem.network_registration.signals.property_changed->disconnect(connections.network_registration_properties_changed);
10+ modem.network_registration.signals.property_changed->disconnect(connections.network_registration_properties_changed);
11 }
12
13 const core::Property<bool>& detail::CachedRadioCell::is_roaming() const
14
15=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp'
16--- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2014-10-13 13:54:05 +0000
17+++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2014-11-10 20:13:24 +0000
18@@ -423,56 +423,8 @@
19
20 network_manager->for_each_device([this](const core::dbus::types::ObjectPath& device_path)
21 {
22- auto device = network_manager->device_for_path(device_path);
23-
24- if (device.type() == xdg::NetworkManager::Device::Type::wifi)
25- {
26- // Make the device known to the cache.
27- std::map<core::dbus::types::ObjectPath, org::freedesktop::NetworkManager::Device>::iterator it;
28- std::tie(it, std::ignore) = cached.wireless_devices.insert(std::make_pair(device_path, device));
29-
30- // Iterate over all currently known wifis
31- it->second.for_each_access_point([this, device_path](const core::dbus::types::ObjectPath& path)
32- {
33- try
34- {
35- on_access_point_added(path, device_path);
36- }
37- catch (const std::exception& e)
38- {
39- VLOG(1) << "Error while creating ap/wifi: " << e.what();
40- }
41- });
42-
43- it->second.signals.scan_done->connect([this]()
44- {
45- signals.wireless_network_scan_finished();
46- });
47-
48- it->second.signals.ap_added->connect([this, device_path](const core::dbus::types::ObjectPath& path)
49- {
50- try
51- {
52- on_access_point_added(path, device_path);
53- }
54- catch (const std::exception& e)
55- {
56- VLOG(1) << "Error while creating ap/wifi: " << e.what();
57- }
58- });
59-
60- it->second.signals.ap_removed->connect([this](const core::dbus::types::ObjectPath& path)
61- {
62- try
63- {
64- on_access_point_removed(path);
65- }
66- catch (const std::exception& e)
67- {
68- VLOG(1) << "Error while removing ap/wifi: " << e.what();
69- }
70- });
71- }
72+ std::unique_lock<std::mutex> ul{cached.guard};
73+ on_device_added(device_path, ul);
74 });
75
76 // Query the initial connectivity state
77@@ -482,6 +434,28 @@
78 characteristics_for_connection(
79 network_manager->properties.primary_connection->get()));
80
81+ network_manager->signals.device_added->connect([this](const core::dbus::types::ObjectPath& path)
82+ {
83+ // We dispatch determining the connection characteristics to unblock
84+ // the bus here.
85+ dispatcher.service.post([this, path]()
86+ {
87+ std::unique_lock<std::mutex> ul{cached.guard};
88+ on_device_added(path, ul);
89+ });
90+ });
91+
92+ network_manager->signals.device_removed->connect([this](const core::dbus::types::ObjectPath& path)
93+ {
94+ // We dispatch determining the connection characteristics to unblock
95+ // the bus here.
96+ dispatcher.service.post([this, path]()
97+ {
98+ std::unique_lock<std::mutex> ul{cached.guard};
99+ on_device_removed(path, ul);
100+ });
101+ });
102+
103 // And we wire up to property changes here
104 network_manager->signals.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)
105 {
106@@ -546,12 +520,79 @@
107 });
108 }
109
110+void connectivity::OfonoNmConnectivityManager::Private::on_device_added(
111+ const core::dbus::types::ObjectPath& device_path,
112+ std::unique_lock<std::mutex>& ul)
113+{
114+ if (cached.wireless_devices.count(device_path) > 0)
115+ return;
116+
117+ auto device = network_manager->device_for_path(device_path);
118+
119+ if (device.type() == xdg::NetworkManager::Device::Type::wifi)
120+ {
121+ // Make the device known to the cache.
122+ std::map<core::dbus::types::ObjectPath, org::freedesktop::NetworkManager::Device>::iterator it;
123+ std::tie(it, std::ignore) = cached.wireless_devices.insert(std::make_pair(device_path, device));
124+
125+ // Iterate over all currently known wifis
126+ it->second.for_each_access_point([this, device_path, &ul](const core::dbus::types::ObjectPath& path)
127+ {
128+ try
129+ {
130+ on_access_point_added(path, device_path, ul);
131+ }
132+ catch (const std::exception& e)
133+ {
134+ VLOG(1) << "Error while creating ap/wifi: " << e.what();
135+ }
136+ });
137+
138+ it->second.signals.scan_done->connect([this]()
139+ {
140+ signals.wireless_network_scan_finished();
141+ });
142+
143+ it->second.signals.ap_added->connect([this, device_path](const core::dbus::types::ObjectPath& path)
144+ {
145+ try
146+ {
147+ std::unique_lock<std::mutex> ul{cached.guard};
148+ on_access_point_added(path, device_path, ul);
149+ }
150+ catch (const std::exception& e)
151+ {
152+ VLOG(1) << "Error while creating ap/wifi: " << e.what();
153+ }
154+ });
155+
156+ it->second.signals.ap_removed->connect([this](const core::dbus::types::ObjectPath& path)
157+ {
158+ try
159+ {
160+ std::unique_lock<std::mutex> ul{cached.guard};
161+ on_access_point_removed(path, ul);
162+ }
163+ catch (const std::exception& e)
164+ {
165+ VLOG(1) << "Error while removing ap/wifi: " << e.what();
166+ }
167+ });
168+ }
169+}
170+
171+void connectivity::OfonoNmConnectivityManager::Private::on_device_removed(
172+ const core::dbus::types::ObjectPath& path,
173+ std::unique_lock<std::mutex>&)
174+{
175+ cached.wireless_devices.erase(path);
176+}
177+
178 void connectivity::OfonoNmConnectivityManager::Private::on_access_point_added(
179 const core::dbus::types::ObjectPath& ap_path,
180- const core::dbus::types::ObjectPath& device_path)
181+ const core::dbus::types::ObjectPath& device_path,
182+ std::unique_lock<std::mutex>& ul)
183 {
184- std::unique_lock<std::mutex> ul(cached.guard);
185-
186 // Let's see if we have a device known for the path. We return early
187 // if we do not know about the device.
188 auto itd = cached.wireless_devices.find(device_path);
189@@ -571,10 +612,10 @@
190 ul.unlock(); signals.wireless_network_added(wifi);
191 }
192
193-void connectivity::OfonoNmConnectivityManager::Private::on_access_point_removed(const core::dbus::types::ObjectPath& ap_path)
194+void connectivity::OfonoNmConnectivityManager::Private::on_access_point_removed(
195+ const core::dbus::types::ObjectPath& ap_path,
196+ std::unique_lock<std::mutex>& ul)
197 {
198- std::unique_lock<std::mutex> ul(cached.guard);
199-
200 // Let's see if we know about the wifi. We return early if not.
201 auto itw = cached.wifis.find(ap_path);
202 if (itw == cached.wifis.end())
203
204=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h'
205--- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h 2014-10-08 14:17:54 +0000
206+++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h 2014-11-10 20:13:24 +0000
207@@ -94,8 +94,10 @@
208
209 // All network stack specific functionality goes here.
210 void setup_network_stack_access();
211- void on_access_point_added(const core::dbus::types::ObjectPath& ap_path, const core::dbus::types::ObjectPath& device_path);
212- void on_access_point_removed(const core::dbus::types::ObjectPath& ap_path);
213+ void on_device_added(const core::dbus::types::ObjectPath& device_path, std::unique_lock<std::mutex>& ul);
214+ void on_device_removed(const core::dbus::types::ObjectPath& device_path, std::unique_lock<std::mutex>& ul);
215+ void on_access_point_added(const core::dbus::types::ObjectPath& ap_path, const core::dbus::types::ObjectPath& device_path, std::unique_lock<std::mutex>& ul);
216+ void on_access_point_removed(const core::dbus::types::ObjectPath& ap_path, std::unique_lock<std::mutex>& ul);
217 com::ubuntu::location::connectivity::Characteristics characteristics_for_connection(const core::dbus::types::ObjectPath& path);
218
219 core::dbus::Bus::Ptr bus;

Subscribers

People subscribed via source and target branches