Commit 05f0f978 authored by Paul Jensen's avatar Paul Jensen Committed by Commit Bot

Replace NetworkChangeNotifierLinux::Thread with SequencedTaskRunner

Dedicated thread wastes resources and causes races in tests where
it can outlive thread pools used by DnsConfigServicePosix's
SerialWorkers.

Bug: 938126
Change-Id: Ic85c83d164cc26cb218c7e2a0304810c6e0c3be4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1548052
Commit-Queue: Paul Jensen <pauljensen@chromium.org>
Reviewed-by: default avatarEric Orth <ericorth@chromium.org>
Cr-Commit-Position: refs/heads/master@{#650602}
parent 9337c34a
...@@ -67,9 +67,12 @@ ...@@ -67,9 +67,12 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "net/base/address_tracker_linux.h" #include "net/base/address_tracker_linux.h"
#include "net/dns/dns_config_service.h" #include "net/dns/dns_config_service_posix.h"
namespace net { namespace net {
...@@ -86,41 +89,32 @@ enum NetId { ...@@ -86,41 +89,32 @@ enum NetId {
// Thread on which we can run DnsConfigService, which requires a TYPE_IO // Thread on which we can run DnsConfigService, which requires a TYPE_IO
// message loop to monitor /system/etc/hosts. // message loop to monitor /system/etc/hosts.
class NetworkChangeNotifierAndroid::DnsConfigServiceThread class NetworkChangeNotifierAndroid::BlockingThreadObjects {
: public base::Thread {
public: public:
DnsConfigServiceThread() BlockingThreadObjects()
: base::Thread("DnsConfigService"), : address_tracker_(base::DoNothing(),
address_tracker_(base::DoNothing(),
base::DoNothing(), base::DoNothing(),
// We're only interested in tunnel interface changes. // We're only interested in tunnel interface changes.
base::Bind(NotifyNetworkChangeNotifierObservers), base::Bind(NotifyNetworkChangeNotifierObservers),
std::unordered_set<std::string>()) {} std::unordered_set<std::string>()) {}
~DnsConfigServiceThread() override { void Init() {
Stop();
}
void Init() override {
address_tracker_.Init(); address_tracker_.Init();
dns_config_service_ = DnsConfigService::CreateSystemService(); dns_config_service_.WatchConfig(
dns_config_service_->WatchConfig(
base::Bind(&NetworkChangeNotifier::SetDnsConfig)); base::Bind(&NetworkChangeNotifier::SetDnsConfig));
} }
void CleanUp() override { dns_config_service_.reset(); }
static void NotifyNetworkChangeNotifierObservers() { static void NotifyNetworkChangeNotifierObservers() {
NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange();
} }
private: private:
std::unique_ptr<DnsConfigService> dns_config_service_; internal::DnsConfigServicePosix dns_config_service_;
// Used to detect tunnel state changes. // Used to detect tunnel state changes.
internal::AddressTrackerLinux address_tracker_; internal::AddressTrackerLinux address_tracker_;
DISALLOW_COPY_AND_ASSIGN(DnsConfigServiceThread); DISALLOW_COPY_AND_ASSIGN(BlockingThreadObjects);
}; };
NetworkChangeNotifierAndroid::~NetworkChangeNotifierAndroid() { NetworkChangeNotifierAndroid::~NetworkChangeNotifierAndroid() {
...@@ -175,7 +169,7 @@ NetworkChangeNotifierAndroid::GetCurrentDefaultNetwork() const { ...@@ -175,7 +169,7 @@ NetworkChangeNotifierAndroid::GetCurrentDefaultNetwork() const {
} }
void NetworkChangeNotifierAndroid::OnConnectionTypeChanged() { void NetworkChangeNotifierAndroid::OnConnectionTypeChanged() {
DnsConfigServiceThread::NotifyNetworkChangeNotifierObservers(); BlockingThreadObjects::NotifyNetworkChangeNotifierObservers();
} }
void NetworkChangeNotifierAndroid::OnMaxBandwidthChanged( void NetworkChangeNotifierAndroid::OnMaxBandwidthChanged(
...@@ -211,13 +205,25 @@ NetworkChangeNotifierAndroid::NetworkChangeNotifierAndroid( ...@@ -211,13 +205,25 @@ NetworkChangeNotifierAndroid::NetworkChangeNotifierAndroid(
NetworkChangeNotifierDelegateAndroid* delegate) NetworkChangeNotifierDelegateAndroid* delegate)
: NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()), : NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()),
delegate_(delegate), delegate_(delegate),
dns_config_service_thread_(new DnsConfigServiceThread()), blocking_thread_runner_(
base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})),
blocking_thread_objects_(
new BlockingThreadObjects(),
// Ensure |blocking_thread_objects_| lives on
// |blocking_thread_runner_| to prevent races where
// NetworkChangeNotifierAndroid outlives
// ScopedTaskEnvironment. https://crbug.com/938126
base::OnTaskRunnerDeleter(blocking_thread_runner_)),
force_network_handles_supported_for_testing_(false) { force_network_handles_supported_for_testing_(false) {
CHECK_EQ(NetId::INVALID, NetworkChangeNotifier::kInvalidNetworkHandle) CHECK_EQ(NetId::INVALID, NetworkChangeNotifier::kInvalidNetworkHandle)
<< "kInvalidNetworkHandle doesn't match NetId::INVALID"; << "kInvalidNetworkHandle doesn't match NetId::INVALID";
delegate_->AddObserver(this); delegate_->AddObserver(this);
dns_config_service_thread_->StartWithOptions( blocking_thread_runner_->PostTask(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); FROM_HERE,
base::BindOnce(&BlockingThreadObjects::Init,
// The Unretained pointer is safe here because it's
// posted before the deleter can post.
base::Unretained(blocking_thread_objects_.get())));
} }
// static // static
......
...@@ -10,10 +10,16 @@ ...@@ -10,10 +10,16 @@
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "net/android/network_change_notifier_delegate_android.h" #include "net/android/network_change_notifier_delegate_android.h"
#include "net/base/net_export.h" #include "net/base/net_export.h"
#include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier.h"
namespace base {
class SequencedTaskRunner;
struct OnTaskRunnerDeleter;
} // namespace base
namespace net { namespace net {
class NetworkChangeNotifierAndroidTest; class NetworkChangeNotifierAndroidTest;
...@@ -81,7 +87,7 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierAndroid ...@@ -81,7 +87,7 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierAndroid
friend class NetworkChangeNotifierAndroidTest; friend class NetworkChangeNotifierAndroidTest;
friend class NetworkChangeNotifierFactoryAndroid; friend class NetworkChangeNotifierFactoryAndroid;
class DnsConfigServiceThread; class BlockingThreadObjects;
// Enable NetworkHandles support for tests. // Enable NetworkHandles support for tests.
void ForceNetworkHandlesSupportedForTesting(); void ForceNetworkHandlesSupportedForTesting();
...@@ -90,7 +96,14 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierAndroid ...@@ -90,7 +96,14 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierAndroid
NetworkChangeNotifierDelegateAndroid* delegate); NetworkChangeNotifierDelegateAndroid* delegate);
NetworkChangeNotifierDelegateAndroid* const delegate_; NetworkChangeNotifierDelegateAndroid* const delegate_;
std::unique_ptr<DnsConfigServiceThread> dns_config_service_thread_; // |blocking_thread_objects_| will live on this runner.
scoped_refptr<base::SequencedTaskRunner> blocking_thread_runner_;
// A collection of objects that must live on blocking sequences. These objects
// listen for notifications and relay the notifications to the registered
// observers without posting back to the thread the object was created on.
// Also used for DnsConfigService which also must live on blocking sequences.
std::unique_ptr<BlockingThreadObjects, base::OnTaskRunnerDeleter>
blocking_thread_objects_;
bool force_network_handles_supported_for_testing_; bool force_network_handles_supported_for_testing_;
DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierAndroid); DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierAndroid);
......
...@@ -118,7 +118,6 @@ AddressTrackerLinux::AddressTrackerLinux() ...@@ -118,7 +118,6 @@ AddressTrackerLinux::AddressTrackerLinux()
address_callback_(base::DoNothing()), address_callback_(base::DoNothing()),
link_callback_(base::DoNothing()), link_callback_(base::DoNothing()),
tunnel_callback_(base::DoNothing()), tunnel_callback_(base::DoNothing()),
watcher_(FROM_HERE),
ignored_interfaces_(), ignored_interfaces_(),
connection_type_initialized_(false), connection_type_initialized_(false),
connection_type_initialized_cv_(&connection_type_lock_), connection_type_initialized_cv_(&connection_type_lock_),
...@@ -135,7 +134,6 @@ AddressTrackerLinux::AddressTrackerLinux( ...@@ -135,7 +134,6 @@ AddressTrackerLinux::AddressTrackerLinux(
address_callback_(address_callback), address_callback_(address_callback),
link_callback_(link_callback), link_callback_(link_callback),
tunnel_callback_(tunnel_callback), tunnel_callback_(tunnel_callback),
watcher_(FROM_HERE),
ignored_interfaces_(ignored_interfaces), ignored_interfaces_(ignored_interfaces),
connection_type_initialized_(false), connection_type_initialized_(false),
connection_type_initialized_cv_(&connection_type_lock_), connection_type_initialized_cv_(&connection_type_lock_),
...@@ -146,9 +144,7 @@ AddressTrackerLinux::AddressTrackerLinux( ...@@ -146,9 +144,7 @@ AddressTrackerLinux::AddressTrackerLinux(
DCHECK(!link_callback.is_null()); DCHECK(!link_callback.is_null());
} }
AddressTrackerLinux::~AddressTrackerLinux() { AddressTrackerLinux::~AddressTrackerLinux() = default;
watcher_.StopWatchingFileDescriptor();
}
void AddressTrackerLinux::Init() { void AddressTrackerLinux::Init() {
netlink_fd_.reset(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)); netlink_fd_.reset(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE));
...@@ -230,19 +226,15 @@ void AddressTrackerLinux::Init() { ...@@ -230,19 +226,15 @@ void AddressTrackerLinux::Init() {
} }
if (tracking_) { if (tracking_) {
rv = base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor( watcher_ = base::FileDescriptorWatcher::WatchReadable(
netlink_fd_.get(), true, base::MessagePumpForIO::WATCH_READ, &watcher_, netlink_fd_.get(),
this); base::BindRepeating(&AddressTrackerLinux::OnFileCanReadWithoutBlocking,
if (rv < 0) { base::Unretained(this)));
PLOG(ERROR) << "Could not watch NETLINK socket";
AbortAndForceOnline();
return;
}
} }
} }
void AddressTrackerLinux::AbortAndForceOnline() { void AddressTrackerLinux::AbortAndForceOnline() {
watcher_.StopWatchingFileDescriptor(); watcher_.reset();
netlink_fd_.reset(); netlink_fd_.reset();
AddressTrackerAutoLock lock(*this, connection_type_lock_); AddressTrackerAutoLock lock(*this, connection_type_lock_);
current_connection_type_ = NetworkChangeNotifier::CONNECTION_UNKNOWN; current_connection_type_ = NetworkChangeNotifier::CONNECTION_UNKNOWN;
...@@ -424,8 +416,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer, ...@@ -424,8 +416,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer,
} }
} }
void AddressTrackerLinux::OnFileCanReadWithoutBlocking(int fd) { void AddressTrackerLinux::OnFileCanReadWithoutBlocking() {
DCHECK_EQ(netlink_fd_.get(), fd);
bool address_changed; bool address_changed;
bool link_changed; bool link_changed;
bool tunnel_changed; bool tunnel_changed;
...@@ -438,8 +429,6 @@ void AddressTrackerLinux::OnFileCanReadWithoutBlocking(int fd) { ...@@ -438,8 +429,6 @@ void AddressTrackerLinux::OnFileCanReadWithoutBlocking(int fd) {
tunnel_callback_.Run(); tunnel_callback_.Run();
} }
void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {}
bool AddressTrackerLinux::IsTunnelInterface(int interface_index) const { bool AddressTrackerLinux::IsTunnelInterface(int interface_index) const {
char buf[IFNAMSIZ] = {0}; char buf[IFNAMSIZ] = {0};
return IsTunnelInterfaceName(get_interface_name_(interface_index, buf)); return IsTunnelInterfaceName(get_interface_name_(interface_index, buf));
......
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/files/scoped_file.h" #include "base/files/scoped_file.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/synchronization/condition_variable.h" #include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
...@@ -32,8 +32,7 @@ namespace internal { ...@@ -32,8 +32,7 @@ namespace internal {
// Keeps track of network interface addresses using rtnetlink. Used by // Keeps track of network interface addresses using rtnetlink. Used by
// NetworkChangeNotifier to provide signals to registered IPAddressObservers. // NetworkChangeNotifier to provide signals to registered IPAddressObservers.
class NET_EXPORT_PRIVATE AddressTrackerLinux class NET_EXPORT_PRIVATE AddressTrackerLinux {
: public base::MessagePumpForIO::FdWatcher {
public: public:
typedef std::map<IPAddress, struct ifaddrmsg> AddressMap; typedef std::map<IPAddress, struct ifaddrmsg> AddressMap;
...@@ -58,7 +57,7 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux ...@@ -58,7 +57,7 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux
const base::Closure& link_callback, const base::Closure& link_callback,
const base::Closure& tunnel_callback, const base::Closure& tunnel_callback,
const std::unordered_set<std::string>& ignored_interfaces); const std::unordered_set<std::string>& ignored_interfaces);
~AddressTrackerLinux() override; virtual ~AddressTrackerLinux();
// In tracking mode, it starts watching the system configuration for // In tracking mode, it starts watching the system configuration for
// changes. The current thread must have a MessageLoopForIO. In // changes. The current thread must have a MessageLoopForIO. In
...@@ -129,9 +128,8 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux ...@@ -129,9 +128,8 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux
// Call when some part of initialization failed; forces online and unblocks. // Call when some part of initialization failed; forces online and unblocks.
void AbortAndForceOnline(); void AbortAndForceOnline();
// MessagePumpForIO::FdWatcher: // Called by |watcher_| when |netlink_fd_| can be read without blocking.
void OnFileCanReadWithoutBlocking(int fd) override; void OnFileCanReadWithoutBlocking();
void OnFileCanWriteWithoutBlocking(int /* fd */) override;
// Does |interface_index| refer to a tunnel interface? // Does |interface_index| refer to a tunnel interface?
bool IsTunnelInterface(int interface_index) const; bool IsTunnelInterface(int interface_index) const;
...@@ -157,7 +155,7 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux ...@@ -157,7 +155,7 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux
// Note that |watcher_| must be inactive when |netlink_fd_| is closed. // Note that |watcher_| must be inactive when |netlink_fd_| is closed.
base::ScopedFD netlink_fd_; base::ScopedFD netlink_fd_;
base::MessagePumpForIO::FdWatchController watcher_; std::unique_ptr<base::FileDescriptorWatcher::Controller> watcher_;
mutable base::Lock address_map_lock_; mutable base::Lock address_map_lock_;
AddressMap address_map_; AddressMap address_map_;
......
...@@ -9,83 +9,73 @@ ...@@ -9,83 +9,73 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "net/base/address_tracker_linux.h" #include "net/base/address_tracker_linux.h"
#include "net/dns/dns_config_service.h" #include "net/dns/dns_config_service_posix.h"
namespace net { namespace net {
class NetworkChangeNotifierLinux::Thread : public base::Thread { // A collection of objects that live on blocking threads.
class NetworkChangeNotifierLinux::BlockingThreadObjects {
public: public:
explicit Thread(const std::unordered_set<std::string>& ignored_interfaces); explicit BlockingThreadObjects(
~Thread() override; const std::unordered_set<std::string>& ignored_interfaces);
// Plumbing for NetworkChangeNotifier::GetCurrentConnectionType. // Plumbing for NetworkChangeNotifier::GetCurrentConnectionType.
// Safe to call from any thread. // Safe to call from any thread.
NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() { NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() {
return address_tracker_->GetCurrentConnectionType(); return address_tracker_.GetCurrentConnectionType();
} }
const internal::AddressTrackerLinux* address_tracker() const { const internal::AddressTrackerLinux* address_tracker() const {
return address_tracker_.get(); return &address_tracker_;
} }
protected: // Begin watching for DNS and netlink changes.
// base::Thread void Init();
void Init() override;
void CleanUp() override;
private: private:
void OnIPAddressChanged(); void OnIPAddressChanged();
void OnLinkChanged(); void OnLinkChanged();
std::unique_ptr<DnsConfigService> dns_config_service_; internal::DnsConfigServicePosix dns_config_service_;
// Used to detect online/offline state and IP address changes. // Used to detect online/offline state and IP address changes.
std::unique_ptr<internal::AddressTrackerLinux> address_tracker_; internal::AddressTrackerLinux address_tracker_;
NetworkChangeNotifier::ConnectionType last_type_; NetworkChangeNotifier::ConnectionType last_type_;
DISALLOW_COPY_AND_ASSIGN(Thread); DISALLOW_COPY_AND_ASSIGN(BlockingThreadObjects);
}; };
NetworkChangeNotifierLinux::Thread::Thread( NetworkChangeNotifierLinux::BlockingThreadObjects::BlockingThreadObjects(
const std::unordered_set<std::string>& ignored_interfaces) const std::unordered_set<std::string>& ignored_interfaces)
: base::Thread("NetworkChangeNotifier"), : address_tracker_(
address_tracker_(new internal::AddressTrackerLinux( base::BindRepeating(&NetworkChangeNotifierLinux::
base::Bind(&NetworkChangeNotifierLinux::Thread::OnIPAddressChanged, BlockingThreadObjects::OnIPAddressChanged,
base::Unretained(this)), base::Unretained(this)),
base::Bind(&NetworkChangeNotifierLinux::Thread::OnLinkChanged, base::BindRepeating(
base::Unretained(this)), &NetworkChangeNotifierLinux::BlockingThreadObjects::OnLinkChanged,
base::Unretained(this)),
base::DoNothing(), base::DoNothing(),
ignored_interfaces)), ignored_interfaces),
last_type_(NetworkChangeNotifier::CONNECTION_NONE) {} last_type_(NetworkChangeNotifier::CONNECTION_NONE) {}
NetworkChangeNotifierLinux::Thread::~Thread() { void NetworkChangeNotifierLinux::BlockingThreadObjects::Init() {
DCHECK(!Thread::IsRunning()); address_tracker_.Init();
}
void NetworkChangeNotifierLinux::Thread::Init() {
address_tracker_->Init();
last_type_ = GetCurrentConnectionType(); last_type_ = GetCurrentConnectionType();
dns_config_service_ = DnsConfigService::CreateSystemService(); dns_config_service_.WatchConfig(
dns_config_service_->WatchConfig(
base::Bind(&NetworkChangeNotifier::SetDnsConfig)); base::Bind(&NetworkChangeNotifier::SetDnsConfig));
} }
void NetworkChangeNotifierLinux::Thread::CleanUp() { void NetworkChangeNotifierLinux::BlockingThreadObjects::OnIPAddressChanged() {
// Delete AddressTrackerLinux before MessageLoop gets deleted as
// AddressTrackerLinux's FileDescriptorWatcher holds a pointer to the
// MessageLoop.
address_tracker_.reset();
dns_config_service_.reset();
}
void NetworkChangeNotifierLinux::Thread::OnIPAddressChanged() {
NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
// When the IP address of a network interface is added/deleted, the // When the IP address of a network interface is added/deleted, the
// connection type may have changed. // connection type may have changed.
OnLinkChanged(); OnLinkChanged();
} }
void NetworkChangeNotifierLinux::Thread::OnLinkChanged() { void NetworkChangeNotifierLinux::BlockingThreadObjects::OnLinkChanged() {
if (last_type_ != GetCurrentConnectionType()) { if (last_type_ != GetCurrentConnectionType()) {
NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange();
last_type_ = GetCurrentConnectionType(); last_type_ = GetCurrentConnectionType();
...@@ -100,19 +90,24 @@ void NetworkChangeNotifierLinux::Thread::OnLinkChanged() { ...@@ -100,19 +90,24 @@ void NetworkChangeNotifierLinux::Thread::OnLinkChanged() {
NetworkChangeNotifierLinux::NetworkChangeNotifierLinux( NetworkChangeNotifierLinux::NetworkChangeNotifierLinux(
const std::unordered_set<std::string>& ignored_interfaces) const std::unordered_set<std::string>& ignored_interfaces)
: NetworkChangeNotifier(NetworkChangeCalculatorParamsLinux()), : NetworkChangeNotifier(NetworkChangeCalculatorParamsLinux()),
notifier_thread_(new Thread(ignored_interfaces)) { blocking_thread_runner_(
// We create this notifier thread because the notification implementation base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})),
// needs a MessageLoopForIO, and there's no guarantee that blocking_thread_objects_(
// MessageLoopCurrent::Get() meets that criterion. new BlockingThreadObjects(ignored_interfaces),
base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); // Ensure |blocking_thread_objects_| lives on
notifier_thread_->StartWithOptions(thread_options); // |blocking_thread_runner_| to prevent races where
// NetworkChangeNotifierLinux outlives
// ScopedTaskEnvironment. https://crbug.com/938126
base::OnTaskRunnerDeleter(blocking_thread_runner_)) {
blocking_thread_runner_->PostTask(
FROM_HERE,
base::BindOnce(&NetworkChangeNotifierLinux::BlockingThreadObjects::Init,
// The Unretained pointer is safe here because it's
// posted before the deleter can post.
base::Unretained(blocking_thread_objects_.get())));
} }
NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() { NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() = default;
// Stopping from here allows us to sanity- check that the notifier
// thread shut down properly.
notifier_thread_->Stop();
}
// static // static
NetworkChangeNotifier::NetworkChangeCalculatorParams NetworkChangeNotifier::NetworkChangeCalculatorParams
...@@ -130,12 +125,12 @@ NetworkChangeNotifierLinux::NetworkChangeCalculatorParamsLinux() { ...@@ -130,12 +125,12 @@ NetworkChangeNotifierLinux::NetworkChangeCalculatorParamsLinux() {
NetworkChangeNotifier::ConnectionType NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierLinux::GetCurrentConnectionType() const { NetworkChangeNotifierLinux::GetCurrentConnectionType() const {
return notifier_thread_->GetCurrentConnectionType(); return blocking_thread_objects_->GetCurrentConnectionType();
} }
const internal::AddressTrackerLinux* const internal::AddressTrackerLinux*
NetworkChangeNotifierLinux::GetAddressTrackerInternal() const { NetworkChangeNotifierLinux::GetAddressTrackerInternal() const {
return notifier_thread_->address_tracker(); return blocking_thread_objects_->address_tracker();
} }
} // namespace net } // namespace net
...@@ -10,9 +10,15 @@ ...@@ -10,9 +10,15 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "net/base/net_export.h" #include "net/base/net_export.h"
#include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier.h"
namespace base {
class SequencedTaskRunner;
struct OnTaskRunnerDeleter;
} // namespace base
namespace net { namespace net {
class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux
...@@ -28,7 +34,7 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux ...@@ -28,7 +34,7 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux
const std::unordered_set<std::string>& ignored_interfaces); const std::unordered_set<std::string>& ignored_interfaces);
private: private:
class Thread; class BlockingThreadObjects;
~NetworkChangeNotifierLinux() override; ~NetworkChangeNotifierLinux() override;
static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsLinux(); static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsLinux();
...@@ -39,11 +45,14 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux ...@@ -39,11 +45,14 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux
const internal::AddressTrackerLinux* GetAddressTrackerInternal() const internal::AddressTrackerLinux* GetAddressTrackerInternal()
const override; const override;
// The thread used to listen for notifications. This relays the notification // |blocking_thread_objects_| will live on this runner.
// to the registered observers without posting back to the thread the object scoped_refptr<base::SequencedTaskRunner> blocking_thread_runner_;
// was created on. // A collection of objects that must live on blocking sequences. These objects
// Also used for DnsConfigService which requires TYPE_IO message loop. // listen for notifications and relay the notifications to the registered
std::unique_ptr<Thread> notifier_thread_; // observers without posting back to the thread the object was created on.
// Also used for DnsConfigService which also must live on blocking sequences.
std::unique_ptr<BlockingThreadObjects, base::OnTaskRunnerDeleter>
blocking_thread_objects_;
DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierLinux); DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierLinux);
}; };
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/threading/scoped_blocking_call.h" #include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "net/base/ip_address.h" #include "net/base/ip_address.h"
...@@ -273,7 +273,7 @@ class DnsConfigServicePosix::Watcher { ...@@ -273,7 +273,7 @@ class DnsConfigServicePosix::Watcher {
void OnConfigChanged(bool succeeded) { void OnConfigChanged(bool succeeded) {
// Ignore transient flutter of resolv.conf by delaying the signal a bit. // Ignore transient flutter of resolv.conf by delaying the signal a bit.
const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(50); const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(50);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&Watcher::OnConfigChangedDelayed, base::BindOnce(&Watcher::OnConfigChangedDelayed,
weak_factory_.GetWeakPtr(), succeeded), weak_factory_.GetWeakPtr(), succeeded),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment