diff options
author | craig.schlenter@chromium.org <craig.schlenter@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-05 18:23:44 +0000 |
---|---|---|
committer | craig.schlenter@chromium.org <craig.schlenter@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-05 18:23:44 +0000 |
commit | 74482ef3290cf71d25bcf9b8d12547363ad8ffe3 (patch) | |
tree | 93c182e30e1ad63f48376d993356cf4726fb88aa | |
parent | 37dd9ae5eb1449c0153b0404d69ae7663253daf4 (diff) | |
download | chromium_src-74482ef3290cf71d25bcf9b8d12547363ad8ffe3.zip chromium_src-74482ef3290cf71d25bcf9b8d12547363ad8ffe3.tar.gz chromium_src-74482ef3290cf71d25bcf9b8d12547363ad8ffe3.tar.bz2 |
Linux: Monitor resolv.conf for changes and use that to reload resolver.
BUG=67734
TEST=manual testing by poking at resolv.conf
Review URL: http://codereview.chromium.org/6903061
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99666 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/base/dns_reload_timer.cc | 100 | ||||
-rw-r--r-- | net/base/dns_reload_timer.h | 22 | ||||
-rw-r--r-- | net/base/dns_reloader.cc | 122 | ||||
-rw-r--r-- | net/base/dns_reloader.h | 24 | ||||
-rw-r--r-- | net/base/dnsrr_resolver.cc | 18 | ||||
-rw-r--r-- | net/base/host_resolver_impl.cc | 21 | ||||
-rw-r--r-- | net/base/host_resolver_impl.h | 6 | ||||
-rw-r--r-- | net/base/host_resolver_proc.cc | 18 | ||||
-rw-r--r-- | net/base/network_change_notifier.cc | 26 | ||||
-rw-r--r-- | net/base/network_change_notifier.h | 21 | ||||
-rw-r--r-- | net/base/network_change_notifier_linux.cc | 58 | ||||
-rw-r--r-- | net/net.gyp | 70 | ||||
-rw-r--r-- | tools/valgrind/memcheck/suppressions.txt | 25 |
13 files changed, 332 insertions, 199 deletions
diff --git a/net/base/dns_reload_timer.cc b/net/base/dns_reload_timer.cc deleted file mode 100644 index 89bda59..0000000 --- a/net/base/dns_reload_timer.cc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/dns_reload_timer.h" - -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) -#include "base/lazy_instance.h" -#include "base/threading/thread_local_storage.h" -#include "base/time.h" - -namespace { - -// On Linux/BSD, changes to /etc/resolv.conf can go unnoticed thus resulting -// in DNS queries failing either because nameservers are unknown on startup -// or because nameserver info has changed as a result of e.g. connecting to -// a new network. Some distributions patch glibc to stat /etc/resolv.conf -// to try to automatically detect such changes but these patches are not -// universal and even patched systems such as Jaunty appear to need calls -// to res_ninit to reload the nameserver information in different threads. -// -// We adopt the Mozilla solution here which is to call res_ninit when -// lookups fail and to rate limit the reloading to once per second per -// thread. -// -// OpenBSD does not have thread-safe res_ninit/res_nclose so we can't do -// the same trick there. - -// Keep a timer per calling thread to rate limit the calling of res_ninit. -class DnsReloadTimer { - public: - // Check if the timer for the calling thread has expired. When no - // timer exists for the calling thread, create one. - bool Expired() { - const base::TimeDelta kRetryTime = base::TimeDelta::FromSeconds(1); - base::TimeTicks now = base::TimeTicks::Now(); - base::TimeTicks* timer_ptr = - static_cast<base::TimeTicks*>(tls_index_.Get()); - - if (!timer_ptr) { - timer_ptr = new base::TimeTicks(); - *timer_ptr = base::TimeTicks::Now(); - tls_index_.Set(timer_ptr); - // Return true to reload dns info on the first call for each thread. - return true; - } else if (now - *timer_ptr > kRetryTime) { - *timer_ptr = now; - return true; - } else { - return false; - } - } - - // Free the allocated timer. - static void SlotReturnFunction(void* data) { - base::TimeTicks* tls_data = static_cast<base::TimeTicks*>(data); - delete tls_data; - } - - private: - friend struct base::DefaultLazyInstanceTraits<DnsReloadTimer>; - - DnsReloadTimer() { - // During testing the DnsReloadTimer Singleton may be created and destroyed - // multiple times. Initialize the ThreadLocalStorage slot only once. - if (!tls_index_.initialized()) - tls_index_.Initialize(SlotReturnFunction); - } - - ~DnsReloadTimer() { - } - - // We use thread local storage to identify which base::TimeTicks to - // interact with. - static base::ThreadLocalStorage::Slot tls_index_ ; - - DISALLOW_COPY_AND_ASSIGN(DnsReloadTimer); -}; - -// A TLS slot to the TimeTicks for the current thread. -// static -base::ThreadLocalStorage::Slot DnsReloadTimer::tls_index_( - base::LINKER_INITIALIZED); - -base::LazyInstance<DnsReloadTimer, - base::LeakyLazyInstanceTraits<DnsReloadTimer> > - g_dns_reload_timer(base::LINKER_INITIALIZED); - -} // namespace - -namespace net { - -bool DnsReloadTimerHasExpired() { - DnsReloadTimer* dns_timer = g_dns_reload_timer.Pointer(); - return dns_timer->Expired(); -} - -} // namespace net - -#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) diff --git a/net/base/dns_reload_timer.h b/net/base/dns_reload_timer.h deleted file mode 100644 index fdd90a7..0000000 --- a/net/base/dns_reload_timer.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_BASE_DNS_RELOAD_TIMER_H_ -#define NET_BASE_DNS_RELOAD_TIMER_H_ -#pragma once - -#include "build/build_config.h" - -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) -namespace net { - -// DnsReloadTimerExpired tests the thread local DNS reload timer and, if it has -// expired, returns true and resets the timer. See comments in -// host_resolver_proc.cc for details. -bool DnsReloadTimerHasExpired(); - -} // namespace net -#endif - -#endif // NET_BASE_DNS_RELOAD_TIMER_H_ diff --git a/net/base/dns_reloader.cc b/net/base/dns_reloader.cc new file mode 100644 index 0000000..d45c145 --- /dev/null +++ b/net/base/dns_reloader.cc @@ -0,0 +1,122 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/dns_reloader.h" + +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) + +#include <resolv.h> + +#include "base/basictypes.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/message_loop.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_local_storage.h" +#include "net/base/network_change_notifier.h" + +namespace { + +// On Linux/BSD, changes to /etc/resolv.conf can go unnoticed thus resulting +// in DNS queries failing either because nameservers are unknown on startup +// or because nameserver info has changed as a result of e.g. connecting to +// a new network. Some distributions patch glibc to stat /etc/resolv.conf +// to try to automatically detect such changes but these patches are not +// universal and even patched systems such as Jaunty appear to need calls +// to res_ninit to reload the nameserver information in different threads. +// +// To fix this, on systems with FilePathWatcher support, we use +// NetworkChangeNotifier::DNSObserver to monitor /etc/resolv.conf to +// enable us to respond to DNS changes and reload the resolver state. +// +// OpenBSD does not have thread-safe res_ninit/res_nclose so we can't do +// the same trick there and most *BSD's don't yet have support for +// FilePathWatcher (but perhaps the new kqueue mac code just needs to be +// ported to *BSD to support that). + +class DnsReloader : public net::NetworkChangeNotifier::DNSObserver { + public: + struct ReloadState { + int resolver_generation; + }; + + // NetworkChangeNotifier::OnDNSChanged methods: + virtual void OnDNSChanged() OVERRIDE { + DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_IO); + base::AutoLock l(lock_); + resolver_generation_++; + } + + void MaybeReload() { + ReloadState* reload_state = static_cast<ReloadState*>(tls_index_.Get()); + base::AutoLock l(lock_); + + if (!reload_state) { + reload_state = new ReloadState(); + reload_state->resolver_generation = resolver_generation_; + res_ninit(&_res); + tls_index_.Set(reload_state); + } else if (reload_state->resolver_generation != resolver_generation_) { + reload_state->resolver_generation = resolver_generation_; + // It is safe to call res_nclose here since we know res_ninit will have + // been called above. + res_nclose(&_res); + res_ninit(&_res); + } + } + + // Free the allocated state. + static void SlotReturnFunction(void* data) { + ReloadState* reload_state = static_cast<ReloadState*>(data); + if (reload_state) + res_nclose(&_res); + delete reload_state; + } + + private: + DnsReloader() : resolver_generation_(0) { + tls_index_.Initialize(SlotReturnFunction); + net::NetworkChangeNotifier::AddDNSObserver(this); + } + + ~DnsReloader() { + NOTREACHED(); // LeakyLazyInstance is not destructed. + } + + base::Lock lock_; // Protects resolver_generation_. + int resolver_generation_; + friend struct base::DefaultLazyInstanceTraits<DnsReloader>; + + // We use thread local storage to identify which ReloadState to interact with. + static base::ThreadLocalStorage::Slot tls_index_ ; + + DISALLOW_COPY_AND_ASSIGN(DnsReloader); +}; + +// A TLS slot to the ReloadState for the current thread. +// static +base::ThreadLocalStorage::Slot DnsReloader::tls_index_( + base::LINKER_INITIALIZED); + +base::LazyInstance<DnsReloader, + base::LeakyLazyInstanceTraits<DnsReloader> > + g_dns_reloader(base::LINKER_INITIALIZED); + +} // namespace + +namespace net { + +void EnsureDnsReloaderInit() { + DnsReloader* t ALLOW_UNUSED = g_dns_reloader.Pointer(); +} + +void DnsReloaderMaybeReload() { + // This routine can be called by any of the DNS worker threads. + DnsReloader* dns_reloader = g_dns_reloader.Pointer(); + dns_reloader->MaybeReload(); +} + +} // namespace net + +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) diff --git a/net/base/dns_reloader.h b/net/base/dns_reloader.h new file mode 100644 index 0000000..899fbf3 --- /dev/null +++ b/net/base/dns_reloader.h @@ -0,0 +1,24 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_DNS_RELOADER_H_ +#define NET_BASE_DNS_RELOADER_H_ +#pragma once + +#include "build/build_config.h" + +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) +namespace net { + +// Call on the network thread before calling DnsReloaderMaybeReload() anywhere. +void EnsureDnsReloaderInit(); + +// Call on the worker thread before doing a DNS lookup to reload the +// resolver for that thread by doing res_ninit() if required. +void DnsReloaderMaybeReload(); + +} // namespace net +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) + +#endif // NET_BASE_DNS_RELOADER_H_ diff --git a/net/base/dnsrr_resolver.cc b/net/base/dnsrr_resolver.cc index 2cfb0cf..e0d43d9 100644 --- a/net/base/dnsrr_resolver.cc +++ b/net/base/dnsrr_resolver.cc @@ -20,7 +20,7 @@ #include "base/synchronization/lock.h" #include "base/task.h" #include "base/threading/worker_pool.h" -#include "net/base/dns_reload_timer.h" +#include "net/base/dns_reloader.h" #include "net/base/dns_util.h" #include "net/base/net_errors.h" @@ -184,26 +184,18 @@ class RRResolverWorker { } bool r = true; +#if defined(OS_MACOSX) || defined(OS_OPENBSD) if ((_res.options & RES_INIT) == 0) { if (res_ninit(&_res) != 0) r = false; } +#else + DnsReloaderMaybeReload(); +#endif if (r) { unsigned long saved_options = _res.options; r = Do(); - -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) - if (!r && DnsReloadTimerHasExpired()) { - // When there's no network connection, _res may not be initialized by - // getaddrinfo. Therefore, we call res_nclose only when there are ns - // entries. - if (_res.nscount > 0) - res_nclose(&_res); - if (res_ninit(&_res) == 0) - r = Do(); - } -#endif _res.options = saved_options; } diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc index 840d263..7d6e3e2 100644 --- a/net/base/host_resolver_impl.cc +++ b/net/base/host_resolver_impl.cc @@ -30,6 +30,7 @@ #include "base/values.h" #include "net/base/address_list.h" #include "net/base/address_list_net_log_param.h" +#include "net/base/dns_reloader.h" #include "net/base/host_port_pair.h" #include "net/base/host_resolver_proc.h" #include "net/base/net_errors.h" @@ -1090,6 +1091,10 @@ HostResolverImpl::HostResolverImpl( additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; #endif NetworkChangeNotifier::AddIPAddressObserver(this); +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) + EnsureDnsReloaderInit(); + NetworkChangeNotifier::AddDNSObserver(this); +#endif } HostResolverImpl::~HostResolverImpl() { @@ -1104,6 +1109,9 @@ HostResolverImpl::~HostResolverImpl() { cur_completing_job_->Cancel(); NetworkChangeNotifier::RemoveIPAddressObserver(this); +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) + NetworkChangeNotifier::RemoveDNSObserver(this); +#endif // Delete the job pools. for (size_t i = 0u; i < arraysize(job_pools_); ++i) @@ -1644,4 +1652,17 @@ void HostResolverImpl::OnIPAddressChanged() { // |this| may be deleted inside AbortAllInProgressJobs(). } +void HostResolverImpl::OnDNSChanged() { + // If the DNS server has changed, existing cached info could be wrong so we + // have to drop our internal cache :( Note that OS level DNS caches, such + // as NSCD's cache should be dropped automatically by the OS when + // resolv.conf changes so we don't need to do anything to clear that cache. + if (cache_.get()) + cache_->clear(); + // Existing jobs will have been sent to the original server so they need to + // be aborted. TODO(Craig): Should these jobs be restarted? + AbortAllInProgressJobs(); + // |this| may be deleted inside AbortAllInProgressJobs(). +} + } // namespace net diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h index 30772df..4c4581e 100644 --- a/net/base/host_resolver_impl.h +++ b/net/base/host_resolver_impl.h @@ -62,7 +62,8 @@ namespace net { class NET_EXPORT HostResolverImpl : public HostResolver, NON_EXPORTED_BASE(public base::NonThreadSafe), - public NetworkChangeNotifier::IPAddressObserver { + public NetworkChangeNotifier::IPAddressObserver, + public NetworkChangeNotifier::DNSObserver { public: // The index into |job_pools_| for the various job pools. Pools with a higher // index have lower priority. @@ -304,6 +305,9 @@ class NET_EXPORT HostResolverImpl retry_factor_ = retry_factor; } + // NetworkChangeNotifier::OnDNSChanged methods: + virtual void OnDNSChanged(); + // Cache of host resolution results. scoped_ptr<HostCache> cache_; diff --git a/net/base/host_resolver_proc.cc b/net/base/host_resolver_proc.cc index 755f119..331675a 100644 --- a/net/base/host_resolver_proc.cc +++ b/net/base/host_resolver_proc.cc @@ -8,7 +8,7 @@ #include "base/logging.h" #include "net/base/address_list.h" -#include "net/base/dns_reload_timer.h" +#include "net/base/dns_reloader.h" #include "net/base/net_errors.h" #include "net/base/sys_addrinfo.h" @@ -183,22 +183,12 @@ int SystemHostResolverProc(const std::string& host, // Restrict result set to only this socket type to avoid duplicates. hints.ai_socktype = SOCK_STREAM; - int err = getaddrinfo(host.c_str(), NULL, &hints, &ai); - bool should_retry = false; #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ !defined(OS_ANDROID) - // If we fail, re-initialise the resolver just in case there have been any - // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info. - if (err && DnsReloadTimerHasExpired()) { - // When there's no network connection, _res may not be initialized by - // getaddrinfo. Therefore, we call res_nclose only when there are ns - // entries. - if (_res.nscount > 0) - res_nclose(&_res); - if (!res_ninit(&_res)) - should_retry = true; - } + DnsReloaderMaybeReload(); #endif + int err = getaddrinfo(host.c_str(), NULL, &hints, &ai); + bool should_retry = false; // If the lookup was restricted (either by address family, or address // detection), and the results where all localhost of a single family, // maybe we should retry. There were several bugs related to these diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index 2eb59ad..29b983e 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc @@ -90,6 +90,13 @@ void NetworkChangeNotifier::AddOnlineStateObserver( } } +void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) { + if (g_network_change_notifier) { + g_network_change_notifier->resolver_state_observer_list_->AddObserver( + observer); + } +} + void NetworkChangeNotifier::RemoveIPAddressObserver( IPAddressObserver* observer) { if (g_network_change_notifier) { @@ -106,13 +113,23 @@ void NetworkChangeNotifier::RemoveOnlineStateObserver( } } +void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) { + if (g_network_change_notifier) { + g_network_change_notifier->resolver_state_observer_list_->RemoveObserver( + observer); + } +} + NetworkChangeNotifier::NetworkChangeNotifier() : ip_address_observer_list_( new ObserverListThreadSafe<IPAddressObserver>( ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)), online_state_observer_list_( new ObserverListThreadSafe<OnlineStateObserver>( - ObserverListBase<OnlineStateObserver>::NOTIFY_EXISTING_ONLY)) { + ObserverListBase<OnlineStateObserver>::NOTIFY_EXISTING_ONLY)), + resolver_state_observer_list_( + new ObserverListThreadSafe<DNSObserver>( + ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)) { DCHECK(!g_network_change_notifier); g_network_change_notifier = this; } @@ -124,6 +141,13 @@ void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() { } } +void NetworkChangeNotifier::NotifyObserversOfDNSChange() { + if (g_network_change_notifier) { + g_network_change_notifier->resolver_state_observer_list_->Notify( + &DNSObserver::OnDNSChanged); + } +} + void NetworkChangeNotifier::NotifyObserversOfOnlineStateChange() { if (g_network_change_notifier) { g_network_change_notifier->online_state_observer_list_->Notify( diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h index dad71c3..39b9e05 100644 --- a/net/base/network_change_notifier.h +++ b/net/base/network_change_notifier.h @@ -50,6 +50,22 @@ class NET_EXPORT NetworkChangeNotifier { DISALLOW_COPY_AND_ASSIGN(OnlineStateObserver); }; + class NET_EXPORT DNSObserver { + public: + virtual ~DNSObserver() {} + + // Will be called when the DNS resolver of the system may have changed. + // This is only used on Linux currently and watches /etc/resolv.conf + // and /etc/hosts + virtual void OnDNSChanged() = 0; + + protected: + DNSObserver() {} + + private: + DISALLOW_COPY_AND_ASSIGN(DNSObserver); + }; + virtual ~NetworkChangeNotifier(); // See the description of NetworkChangeNotifier::IsOffline(). @@ -89,6 +105,7 @@ class NET_EXPORT NetworkChangeNotifier { // thread), in which case it will simply do nothing. static void AddIPAddressObserver(IPAddressObserver* observer); static void AddOnlineStateObserver(OnlineStateObserver* observer); + static void AddDNSObserver(DNSObserver* observer); // Unregisters |observer| from receiving notifications. This must be called // on the same thread on which AddObserver() was called. Like AddObserver(), @@ -99,6 +116,7 @@ class NET_EXPORT NetworkChangeNotifier { // there's no reason to use the API in this risky way, so don't do it. static void RemoveIPAddressObserver(IPAddressObserver* observer); static void RemoveOnlineStateObserver(OnlineStateObserver* observer); + static void RemoveDNSObserver(DNSObserver* observer); // Allow unit tests to trigger notifications. static void NotifyObserversOfIPAddressChangeForTests() { @@ -113,12 +131,15 @@ class NET_EXPORT NetworkChangeNotifier { // tests. static void NotifyObserversOfIPAddressChange(); static void NotifyObserversOfOnlineStateChange(); + static void NotifyObserversOfDNSChange(); private: const scoped_refptr<ObserverListThreadSafe<IPAddressObserver> > ip_address_observer_list_; const scoped_refptr<ObserverListThreadSafe<OnlineStateObserver> > online_state_observer_list_; + const scoped_refptr<ObserverListThreadSafe<DNSObserver> > + resolver_state_observer_list_; DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier); }; diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc index 3937de0..45ee139 100644 --- a/net/base/network_change_notifier_linux.cc +++ b/net/base/network_change_notifier_linux.cc @@ -7,19 +7,48 @@ #include <errno.h> #include <sys/socket.h> +#include "base/bind.h" +#include "base/callback_old.h" #include "base/compiler_specific.h" #include "base/eintr_wrapper.h" +#include "base/file_util.h" +#include "base/files/file_path_watcher.h" #include "base/task.h" #include "base/threading/thread.h" #include "net/base/net_errors.h" #include "net/base/network_change_notifier_netlink_linux.h" +using ::base::files::FilePathWatcher; + namespace net { namespace { const int kInvalidSocket = -1; +class DNSWatchDelegate : public FilePathWatcher::Delegate { + public: + explicit DNSWatchDelegate(Callback0::Type* callback) + : callback_(callback) {} + virtual ~DNSWatchDelegate() {} + // FilePathWatcher::Delegate interface + virtual void OnFilePathChanged(const FilePath& path) OVERRIDE; + virtual void OnFilePathError(const FilePath& path) OVERRIDE; + private: + scoped_ptr<Callback0::Type> callback_; + DISALLOW_COPY_AND_ASSIGN(DNSWatchDelegate); +}; + +void DNSWatchDelegate::OnFilePathChanged(const FilePath& path) { + // Calls NetworkChangeNotifier::NotifyObserversOfDNSChange(). + if (callback_.get()) + callback_->Run(); +} + +void DNSWatchDelegate::OnFilePathError(const FilePath& path) { + LOG(ERROR) << "DNSWatchDelegate::OnFilePathError for " << path.value(); +} + } // namespace class NetworkChangeNotifierLinux::Thread @@ -42,6 +71,10 @@ class NetworkChangeNotifierLinux::Thread NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); } + void NotifyObserversOfDNSChange() { + NetworkChangeNotifier::NotifyObserversOfDNSChange(); + } + // Starts listening for netlink messages. Also handles the messages if there // are any available on the netlink socket. void ListenForNotifications(); @@ -58,17 +91,36 @@ class NetworkChangeNotifierLinux::Thread // Technically only needed for ChromeOS, but it's ugly to #ifdef out. ScopedRunnableMethodFactory<Thread> method_factory_; + // Used to watch for changes to /etc/resolv.conf and /etc/hosts. + scoped_ptr<base::files::FilePathWatcher> resolv_file_watcher_; + scoped_ptr<base::files::FilePathWatcher> hosts_file_watcher_; + scoped_refptr<DNSWatchDelegate> file_watcher_delegate_; + DISALLOW_COPY_AND_ASSIGN(Thread); }; NetworkChangeNotifierLinux::Thread::Thread() : base::Thread("NetworkChangeNotifier"), netlink_fd_(kInvalidSocket), - ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} + ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { +} NetworkChangeNotifierLinux::Thread::~Thread() {} void NetworkChangeNotifierLinux::Thread::Init() { + resolv_file_watcher_.reset(new FilePathWatcher); + hosts_file_watcher_.reset(new FilePathWatcher); + file_watcher_delegate_ = new DNSWatchDelegate(NewCallback(this, + &NetworkChangeNotifierLinux::Thread::NotifyObserversOfDNSChange)); + if (!resolv_file_watcher_->Watch( + FilePath(FILE_PATH_LITERAL("/etc/resolv.conf")), + file_watcher_delegate_.get())) { + LOG(ERROR) << "Failed to setup watch for /etc/resolv.conf"; + } + if (!hosts_file_watcher_->Watch(FilePath(FILE_PATH_LITERAL("/etc/hosts")), + file_watcher_delegate_.get())) { + LOG(ERROR) << "Failed to setup watch for /etc/hosts"; + } netlink_fd_ = InitializeNetlinkSocket(); if (netlink_fd_ < 0) { netlink_fd_ = kInvalidSocket; @@ -84,6 +136,10 @@ void NetworkChangeNotifierLinux::Thread::CleanUp() { netlink_fd_ = kInvalidSocket; netlink_watcher_.StopWatchingFileDescriptor(); } + // Kill watchers early to make sure they won't try to call + // into us via the delegate during destruction. + resolv_file_watcher_.reset(); + hosts_file_watcher_.reset(); } void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) { diff --git a/net/net.gyp b/net/net.gyp index a551c5e..bd6bbd2 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -82,16 +82,16 @@ 'base/default_origin_bound_cert_store.h', 'base/directory_lister.cc', 'base/directory_lister.h', - 'base/dns_reload_timer.cc', - 'base/dns_reload_timer.h', - 'base/dnssec_chain_verifier.cc', - 'base/dnssec_chain_verifier.h', - 'base/dnssec_keyset.cc', - 'base/dnssec_keyset.h', + 'base/dns_reloader.cc', + 'base/dns_reloader.h', 'base/dns_util.cc', 'base/dns_util.h', 'base/dnsrr_resolver.cc', 'base/dnsrr_resolver.h', + 'base/dnssec_chain_verifier.cc', + 'base/dnssec_chain_verifier.h', + 'base/dnssec_keyset.cc', + 'base/dnssec_keyset.h', 'base/escape.cc', 'base/escape.h', 'base/escape_icu.cc', @@ -209,6 +209,8 @@ 'base/ssl_info.h', 'base/static_cookie_policy.cc', 'base/static_cookie_policy.h', + 'base/sys_addrinfo.h', + 'base/sys_byteorder.h', 'base/test_data_stream.cc', 'base/test_data_stream.h', 'base/test_root_certs.cc', @@ -219,8 +221,6 @@ 'base/test_root_certs_win.cc', 'base/transport_security_state.cc', 'base/transport_security_state.h', - 'base/sys_addrinfo.h', - 'base/sys_byteorder.h', 'base/upload_data.cc', 'base/upload_data.h', 'base/upload_data_stream.cc', @@ -229,15 +229,15 @@ 'base/winsock_init.h', 'base/winsock_util.cc', 'base/winsock_util.h', + 'base/x509_cert_types.cc', + 'base/x509_cert_types.h', + 'base/x509_cert_types_mac.cc', 'base/x509_certificate.cc', 'base/x509_certificate.h', 'base/x509_certificate_mac.cc', 'base/x509_certificate_nss.cc', 'base/x509_certificate_openssl.cc', 'base/x509_certificate_win.cc', - 'base/x509_cert_types.cc', - 'base/x509_cert_types.h', - 'base/x509_cert_types_mac.cc', 'base/x509_util_openssl.cc', 'base/x509_util_openssl.h', 'disk_cache/addr.cc', @@ -260,8 +260,6 @@ 'disk_cache/eviction.cc', 'disk_cache/eviction.h', 'disk_cache/experiments.h', - 'disk_cache/net_log_parameters.cc', - 'disk_cache/net_log_parameters.h', 'disk_cache/file.cc', 'disk_cache/file.h', 'disk_cache/file_block.h', @@ -285,6 +283,8 @@ 'disk_cache/mem_entry_impl.h', 'disk_cache/mem_rankings.cc', 'disk_cache/mem_rankings.h', + 'disk_cache/net_log_parameters.cc', + 'disk_cache/net_log_parameters.h', 'disk_cache/rankings.cc', 'disk_cache/rankings.h', 'disk_cache/sparse_control.cc', @@ -370,8 +370,8 @@ 'http/http_auth_handler_digest.h', 'http/http_auth_handler_factory.cc', 'http/http_auth_handler_factory.h', - 'http/http_auth_handler_negotiate.h', 'http/http_auth_handler_negotiate.cc', + 'http/http_auth_handler_negotiate.h', 'http/http_auth_handler_ntlm.cc', 'http/http_auth_handler_ntlm.h', 'http/http_auth_handler_ntlm_portable.cc', @@ -400,6 +400,12 @@ 'http/http_network_session_peer.h', 'http/http_network_transaction.cc', 'http/http_network_transaction.h', + 'http/http_proxy_client_socket.cc', + 'http/http_proxy_client_socket.h', + 'http/http_proxy_client_socket_pool.cc', + 'http/http_proxy_client_socket_pool.h', + 'http/http_proxy_utils.cc', + 'http/http_proxy_utils.h', 'http/http_request_headers.cc', 'http/http_request_headers.h', 'http/http_request_info.cc', @@ -423,19 +429,9 @@ 'http/http_stream_parser.h', 'http/http_transaction.h', 'http/http_transaction_factory.h', - 'http/url_security_manager.h', - 'http/url_security_manager.cc', - 'http/url_security_manager_posix.cc', - 'http/url_security_manager_win.cc', - 'http/http_proxy_client_socket.cc', - 'http/http_proxy_client_socket.h', - 'http/http_proxy_client_socket_pool.cc', - 'http/http_proxy_client_socket_pool.h', - 'http/http_proxy_utils.cc', - 'http/http_proxy_utils.h', 'http/http_util.cc', - 'http/http_util_icu.cc', 'http/http_util.h', + 'http/http_util_icu.cc', 'http/http_vary_data.cc', 'http/http_vary_data.h', 'http/http_version.h', @@ -444,14 +440,18 @@ 'http/partial_data.cc', 'http/partial_data.h', 'http/proxy_client_socket.h', + 'http/url_security_manager.cc', + 'http/url_security_manager.h', + 'http/url_security_manager_posix.cc', + 'http/url_security_manager_win.cc', 'ocsp/nss_ocsp.cc', 'ocsp/nss_ocsp.h', + 'proxy/dhcp_proxy_script_adapter_fetcher_win.cc', + 'proxy/dhcp_proxy_script_adapter_fetcher_win.h', 'proxy/dhcp_proxy_script_fetcher.cc', 'proxy/dhcp_proxy_script_fetcher.h', 'proxy/dhcp_proxy_script_fetcher_factory.cc', 'proxy/dhcp_proxy_script_fetcher_factory.h', - 'proxy/dhcp_proxy_script_adapter_fetcher_win.cc', - 'proxy/dhcp_proxy_script_adapter_fetcher_win.h', 'proxy/dhcp_proxy_script_fetcher_win.cc', 'proxy/dhcp_proxy_script_fetcher_win.h', 'proxy/dhcpcsvc_init_win.cc', @@ -500,8 +500,8 @@ 'proxy/proxy_script_fetcher_impl.cc', 'proxy/proxy_script_fetcher_impl.h', 'proxy/proxy_server.cc', - 'proxy/proxy_server_mac.cc', 'proxy/proxy_server.h', + 'proxy/proxy_server_mac.cc', 'proxy/proxy_service.cc', 'proxy/proxy_service.h', 'proxy/sync_host_resolver.h', @@ -511,8 +511,8 @@ 'socket/client_socket_factory.h', 'socket/client_socket_handle.cc', 'socket/client_socket_handle.h', - 'socket/client_socket_pool.h', 'socket/client_socket_pool.cc', + 'socket/client_socket_pool.h', 'socket/client_socket_pool_base.cc', 'socket/client_socket_pool_base.h', 'socket/client_socket_pool_histograms.cc', @@ -545,12 +545,12 @@ 'socket/ssl_client_socket_win.h', 'socket/ssl_error_params.cc', 'socket/ssl_error_params.h', + 'socket/ssl_host_info.cc', + 'socket/ssl_host_info.h', 'socket/ssl_server_socket.h', 'socket/ssl_server_socket_nss.cc', 'socket/ssl_server_socket_nss.h', 'socket/ssl_server_socket_openssl.cc', - 'socket/ssl_host_info.cc', - 'socket/ssl_host_info.h', 'socket/stream_socket.cc', 'socket/stream_socket.h', 'socket/tcp_client_socket.cc', @@ -602,10 +602,10 @@ 'spdy/spdy_websocket_stream.h', 'third_party/mozilla_security_manager/nsKeygenHandler.cpp', 'third_party/mozilla_security_manager/nsKeygenHandler.h', - 'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp', - 'third_party/mozilla_security_manager/nsNSSCertificateDB.h', 'third_party/mozilla_security_manager/nsNSSCertTrust.cpp', 'third_party/mozilla_security_manager/nsNSSCertTrust.h', + 'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp', + 'third_party/mozilla_security_manager/nsNSSCertificateDB.h', 'third_party/mozilla_security_manager/nsPKCS12Blob.cpp', 'third_party/mozilla_security_manager/nsPKCS12Blob.h', 'udp/datagram_client_socket.h', @@ -620,8 +620,8 @@ 'udp/udp_socket_libevent.h', 'udp/udp_socket_win.cc', 'udp/udp_socket_win.h', - 'url_request/https_prober.h', 'url_request/https_prober.cc', + 'url_request/https_prober.h', 'url_request/url_request.cc', 'url_request/url_request.h', 'url_request/url_request_about_job.cc', @@ -664,8 +664,8 @@ 'url_request/url_request_throttler_entry.cc', 'url_request/url_request_throttler_entry.h', 'url_request/url_request_throttler_entry_interface.h', - 'url_request/url_request_throttler_header_adapter.h', 'url_request/url_request_throttler_header_adapter.cc', + 'url_request/url_request_throttler_header_adapter.h', 'url_request/url_request_throttler_header_interface.h', 'url_request/url_request_throttler_manager.cc', 'url_request/url_request_throttler_manager.h', diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt index 94ed770..77f835b 100644 --- a/tools/valgrind/memcheck/suppressions.txt +++ b/tools/valgrind/memcheck/suppressions.txt @@ -2239,18 +2239,6 @@ fun:_ZN4base6Thread10ThreadMainEv } { - bug_46161 - Memcheck:Leak - fun:_Znw* - fun:*DnsReloadTimer7ExpiredEv - fun:_ZN3net24DnsReloadTimerHasExpiredEv - fun:_ZN3net22SystemHostResolverProcERKSsNS_13AddressFamilyEiPNS_11AddressListEPi - fun:_ZN3net*15ResolveAddrInfoEPNS_16HostResolverProc* - fun:_ZN3net16HostResolverImpl3Job8DoLookup* - fun:_Z16DispatchToMethodIN3net16HostResolverImpl* - fun:_ZN14RunnableMethodIN3net16HostResolverImpl* -} -{ bug_46250 Memcheck:Leak fun:_Znw* @@ -4804,6 +4792,19 @@ fun:_ZN3net16HttpStreamParser21DoReadHeadersCompleteEi } { + bug_89553 + Memcheck:Leak + fun:_Znw* + fun:_ZN12_GLOBAL__N_111DnsReloader11MaybeReloadEv + fun:_ZN3net22DnsReloaderMaybeReloadEv + fun:_ZN3net22SystemHostResolverProcERKSsNS_13AddressFamilyEiPNS_11AddressListEPi + ... + fun:_ZN3net*15ResolveAddrInfoEPNS_16HostResolverProc* + fun:_ZN3net16HostResolverImpl3Job8DoLookup* + fun:_Z16DispatchToMethodIN3net16HostResolverImpl* + fun:_ZN14RunnableMethodIN3net16HostResolverImpl* +} +{ bug_89677 Memcheck:Leak fun:_Znw* |