summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcraig.schlenter@chromium.org <craig.schlenter@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-05 18:23:44 +0000
committercraig.schlenter@chromium.org <craig.schlenter@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-05 18:23:44 +0000
commit74482ef3290cf71d25bcf9b8d12547363ad8ffe3 (patch)
tree93c182e30e1ad63f48376d993356cf4726fb88aa
parent37dd9ae5eb1449c0153b0404d69ae7663253daf4 (diff)
downloadchromium_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.cc100
-rw-r--r--net/base/dns_reload_timer.h22
-rw-r--r--net/base/dns_reloader.cc122
-rw-r--r--net/base/dns_reloader.h24
-rw-r--r--net/base/dnsrr_resolver.cc18
-rw-r--r--net/base/host_resolver_impl.cc21
-rw-r--r--net/base/host_resolver_impl.h6
-rw-r--r--net/base/host_resolver_proc.cc18
-rw-r--r--net/base/network_change_notifier.cc26
-rw-r--r--net/base/network_change_notifier.h21
-rw-r--r--net/base/network_change_notifier_linux.cc58
-rw-r--r--net/net.gyp70
-rw-r--r--tools/valgrind/memcheck/suppressions.txt25
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*