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
=== modified file 'src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.cpp'
--- src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.cpp 2014-10-13 15:20:56 +0000
+++ src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.cpp 2014-11-10 20:13:24 +0000
@@ -172,8 +172,7 @@
172172
173detail::CachedRadioCell::~CachedRadioCell()173detail::CachedRadioCell::~CachedRadioCell()
174{174{
175 // TODO(tvoss): Reenable this once we know why the modem cache gets flushed.175 modem.network_registration.signals.property_changed->disconnect(connections.network_registration_properties_changed);
176 // modem.network_registration.signals.property_changed->disconnect(connections.network_registration_properties_changed);
177}176}
178177
179const core::Property<bool>& detail::CachedRadioCell::is_roaming() const178const core::Property<bool>& detail::CachedRadioCell::is_roaming() const
180179
=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp'
--- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2014-10-13 13:54:05 +0000
+++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2014-11-10 20:13:24 +0000
@@ -423,56 +423,8 @@
423423
424 network_manager->for_each_device([this](const core::dbus::types::ObjectPath& device_path)424 network_manager->for_each_device([this](const core::dbus::types::ObjectPath& device_path)
425 {425 {
426 auto device = network_manager->device_for_path(device_path);426 std::unique_lock<std::mutex> ul{cached.guard};
427427 on_device_added(device_path, ul);
428 if (device.type() == xdg::NetworkManager::Device::Type::wifi)
429 {
430 // Make the device known to the cache.
431 std::map<core::dbus::types::ObjectPath, org::freedesktop::NetworkManager::Device>::iterator it;
432 std::tie(it, std::ignore) = cached.wireless_devices.insert(std::make_pair(device_path, device));
433
434 // Iterate over all currently known wifis
435 it->second.for_each_access_point([this, device_path](const core::dbus::types::ObjectPath& path)
436 {
437 try
438 {
439 on_access_point_added(path, device_path);
440 }
441 catch (const std::exception& e)
442 {
443 VLOG(1) << "Error while creating ap/wifi: " << e.what();
444 }
445 });
446
447 it->second.signals.scan_done->connect([this]()
448 {
449 signals.wireless_network_scan_finished();
450 });
451
452 it->second.signals.ap_added->connect([this, device_path](const core::dbus::types::ObjectPath& path)
453 {
454 try
455 {
456 on_access_point_added(path, device_path);
457 }
458 catch (const std::exception& e)
459 {
460 VLOG(1) << "Error while creating ap/wifi: " << e.what();
461 }
462 });
463
464 it->second.signals.ap_removed->connect([this](const core::dbus::types::ObjectPath& path)
465 {
466 try
467 {
468 on_access_point_removed(path);
469 }
470 catch (const std::exception& e)
471 {
472 VLOG(1) << "Error while removing ap/wifi: " << e.what();
473 }
474 });
475 }
476 });428 });
477429
478 // Query the initial connectivity state430 // Query the initial connectivity state
@@ -482,6 +434,28 @@
482 characteristics_for_connection(434 characteristics_for_connection(
483 network_manager->properties.primary_connection->get()));435 network_manager->properties.primary_connection->get()));
484436
437 network_manager->signals.device_added->connect([this](const core::dbus::types::ObjectPath& path)
438 {
439 // We dispatch determining the connection characteristics to unblock
440 // the bus here.
441 dispatcher.service.post([this, path]()
442 {
443 std::unique_lock<std::mutex> ul{cached.guard};
444 on_device_added(path, ul);
445 });
446 });
447
448 network_manager->signals.device_removed->connect([this](const core::dbus::types::ObjectPath& path)
449 {
450 // We dispatch determining the connection characteristics to unblock
451 // the bus here.
452 dispatcher.service.post([this, path]()
453 {
454 std::unique_lock<std::mutex> ul{cached.guard};
455 on_device_removed(path, ul);
456 });
457 });
458
485 // And we wire up to property changes here459 // And we wire up to property changes here
486 network_manager->signals.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)460 network_manager->signals.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)
487 {461 {
@@ -546,12 +520,79 @@
546 });520 });
547}521}
548522
523void connectivity::OfonoNmConnectivityManager::Private::on_device_added(
524 const core::dbus::types::ObjectPath& device_path,
525 std::unique_lock<std::mutex>& ul)
526{
527 if (cached.wireless_devices.count(device_path) > 0)
528 return;
529
530 auto device = network_manager->device_for_path(device_path);
531
532 if (device.type() == xdg::NetworkManager::Device::Type::wifi)
533 {
534 // Make the device known to the cache.
535 std::map<core::dbus::types::ObjectPath, org::freedesktop::NetworkManager::Device>::iterator it;
536 std::tie(it, std::ignore) = cached.wireless_devices.insert(std::make_pair(device_path, device));
537
538 // Iterate over all currently known wifis
539 it->second.for_each_access_point([this, device_path, &ul](const core::dbus::types::ObjectPath& path)
540 {
541 try
542 {
543 on_access_point_added(path, device_path, ul);
544 }
545 catch (const std::exception& e)
546 {
547 VLOG(1) << "Error while creating ap/wifi: " << e.what();
548 }
549 });
550
551 it->second.signals.scan_done->connect([this]()
552 {
553 signals.wireless_network_scan_finished();
554 });
555
556 it->second.signals.ap_added->connect([this, device_path](const core::dbus::types::ObjectPath& path)
557 {
558 try
559 {
560 std::unique_lock<std::mutex> ul{cached.guard};
561 on_access_point_added(path, device_path, ul);
562 }
563 catch (const std::exception& e)
564 {
565 VLOG(1) << "Error while creating ap/wifi: " << e.what();
566 }
567 });
568
569 it->second.signals.ap_removed->connect([this](const core::dbus::types::ObjectPath& path)
570 {
571 try
572 {
573 std::unique_lock<std::mutex> ul{cached.guard};
574 on_access_point_removed(path, ul);
575 }
576 catch (const std::exception& e)
577 {
578 VLOG(1) << "Error while removing ap/wifi: " << e.what();
579 }
580 });
581 }
582}
583
584void connectivity::OfonoNmConnectivityManager::Private::on_device_removed(
585 const core::dbus::types::ObjectPath& path,
586 std::unique_lock<std::mutex>&)
587{
588 cached.wireless_devices.erase(path);
589}
590
549void connectivity::OfonoNmConnectivityManager::Private::on_access_point_added(591void connectivity::OfonoNmConnectivityManager::Private::on_access_point_added(
550 const core::dbus::types::ObjectPath& ap_path,592 const core::dbus::types::ObjectPath& ap_path,
551 const core::dbus::types::ObjectPath& device_path)593 const core::dbus::types::ObjectPath& device_path,
594 std::unique_lock<std::mutex>& ul)
552{595{
553 std::unique_lock<std::mutex> ul(cached.guard);
554
555 // Let's see if we have a device known for the path. We return early596 // Let's see if we have a device known for the path. We return early
556 // if we do not know about the device.597 // if we do not know about the device.
557 auto itd = cached.wireless_devices.find(device_path);598 auto itd = cached.wireless_devices.find(device_path);
@@ -571,10 +612,10 @@
571 ul.unlock(); signals.wireless_network_added(wifi);612 ul.unlock(); signals.wireless_network_added(wifi);
572}613}
573614
574void connectivity::OfonoNmConnectivityManager::Private::on_access_point_removed(const core::dbus::types::ObjectPath& ap_path)615void connectivity::OfonoNmConnectivityManager::Private::on_access_point_removed(
616 const core::dbus::types::ObjectPath& ap_path,
617 std::unique_lock<std::mutex>& ul)
575{618{
576 std::unique_lock<std::mutex> ul(cached.guard);
577
578 // Let's see if we know about the wifi. We return early if not.619 // Let's see if we know about the wifi. We return early if not.
579 auto itw = cached.wifis.find(ap_path);620 auto itw = cached.wifis.find(ap_path);
580 if (itw == cached.wifis.end())621 if (itw == cached.wifis.end())
581622
=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h'
--- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h 2014-10-08 14:17:54 +0000
+++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h 2014-11-10 20:13:24 +0000
@@ -94,8 +94,10 @@
9494
95 // All network stack specific functionality goes here.95 // All network stack specific functionality goes here.
96 void setup_network_stack_access();96 void setup_network_stack_access();
97 void on_access_point_added(const core::dbus::types::ObjectPath& ap_path, const core::dbus::types::ObjectPath& device_path);97 void on_device_added(const core::dbus::types::ObjectPath& device_path, std::unique_lock<std::mutex>& ul);
98 void on_access_point_removed(const core::dbus::types::ObjectPath& ap_path);98 void on_device_removed(const core::dbus::types::ObjectPath& device_path, std::unique_lock<std::mutex>& ul);
99 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);
100 void on_access_point_removed(const core::dbus::types::ObjectPath& ap_path, std::unique_lock<std::mutex>& ul);
99 com::ubuntu::location::connectivity::Characteristics characteristics_for_connection(const core::dbus::types::ObjectPath& path); 101 com::ubuntu::location::connectivity::Characteristics characteristics_for_connection(const core::dbus::types::ObjectPath& path);
100102
101 core::dbus::Bus::Ptr bus;103 core::dbus::Bus::Ptr bus;

Subscribers

People subscribed via source and target branches