Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Unified Diff: net/base/dns_reload_timer.cc

Issue 6033006: Use FileWatcher to watch system resolver config, on systems that require... Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/dns_reload_timer.h ('k') | net/base/dnsrr_resolver.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/dns_reload_timer.cc
===================================================================
--- net/base/dns_reload_timer.cc (revision 70147)
+++ net/base/dns_reload_timer.cc (working copy)
@@ -4,12 +4,20 @@
#include "net/base/dns_reload_timer.h"
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
+#if WATCH_RESOLV_CONF
+#include <resolv.h>
+
+#include "base/file_path.h"
#include "base/lazy_instance.h"
+#include "base/scoped_ptr.h"
+#include "base/lock.h"
+#include "base/task.h"
+#include "base/thread.h"
#include "base/thread_local_storage.h"
#include "base/time.h"
+#include "chrome/browser/file_path_watcher/file_path_watcher.h"
willchan no longer on Chromium 2011/01/04 23:50:41 net is a lower level module than chrome. chrome d
-namespace {
+namespace net {
// On Linux/BSD, changes to /etc/resolv.conf can go unnoticed thus resulting
// in DNS queries failing either because nameservers are unknown on startup
@@ -29,38 +37,75 @@
// Keep a timer per calling thread to rate limit the calling of res_ninit.
class DnsReloadTimer {
public:
+
+ bool ResolvConfUpdated() {
+ struct DnsReloadTimer::LocalState* local_state = GetLocalState();
+ AutoLock l(lock_);
+ if (local_state->resolv_conf_generation < resolv_conf_generation_ &&
+ Expired()) {
+ local_state->resolv_conf_generation = resolv_conf_generation_;
+ return true;
+ }
+ return false;
+ }
+
// 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);
+ struct DnsReloadTimer::LocalState* local_state = GetLocalState();
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.
+ if (now - local_state->timer > kRetryTime) {
+ local_state->timer = now;
return true;
- } else if (now - *timer_ptr > kRetryTime) {
- *timer_ptr = now;
- return true;
} else {
return false;
}
}
- // Free the allocated timer.
+ // Free the allocated LocalState.
static void SlotReturnFunction(void* data) {
- base::TimeTicks* tls_data = static_cast<base::TimeTicks*>(data);
+ DnsReloadTimer::LocalState* tls_data =
+ static_cast<DnsReloadTimer::LocalState*>(data);
delete tls_data;
}
+ // Installs FileWatcher for _PATH_RESCONF (i.e. /etc/resolv.conf).
+ // Must be run on file thread.
+ void InitResolvConfWatcher();
+
private:
friend struct base::DefaultLazyInstanceTraits<DnsReloadTimer>;
- DnsReloadTimer() {
+ // One LocalState struct is kept in TLS.
+ struct LocalState {
+ base::TimeTicks timer; // Reload timer, used to rate-limit reloads.
+ int resolv_conf_generation; // resolv.conf generation known to this thread.
+ };
+
+ class ResolvConfWatcherDelegate : public FilePathWatcher::Delegate {
+ public:
+ explicit ResolvConfWatcherDelegate(int* conf_generation, Lock* lock)
+ : conf_generation_(conf_generation), lock_(lock) {
+ }
+
+ virtual void OnFilePathChanged(const FilePath& path) {
+ AutoLock l(*lock_);
+ (*conf_generation_)++;
+ LOG(INFO) << _PATH_RESCONF << " updated, new generation: "
+ << *conf_generation_;
+ }
+ private:
+ int* conf_generation_;
+ Lock* lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResolvConfWatcherDelegate);
+ };
+
+ // Generation starts at 1 so that all threads reload resolv.conf
+ // on first invocation.
+ DnsReloadTimer() : resolv_conf_generation_(1) {
// During testing the DnsReloadTimer Singleton may be created and destroyed
// multiple times. Initialize the ThreadLocalStorage slot only once.
if (!tls_index_.initialized())
@@ -70,30 +115,94 @@
~DnsReloadTimer() {
}
+ DnsReloadTimer::LocalState* GetLocalState();
+
+ Lock lock_; // Protects resolv_conf_generation_
+ int resolv_conf_generation_;
+
+ scoped_ptr<FilePathWatcher> resolv_conf_watcher_;
+ scoped_ptr<ResolvConfWatcherDelegate> resolv_conf_watcher_delegate_;
+
// We use thread local storage to identify which base::TimeTicks to
// interact with.
- static ThreadLocalStorage::Slot tls_index_ ;
+ static ThreadLocalStorage::Slot tls_index_;
DISALLOW_COPY_AND_ASSIGN(DnsReloadTimer);
};
+void DnsReloadTimer::InitResolvConfWatcher() {
+ resolv_conf_watcher_.reset(new FilePathWatcher());
+ resolv_conf_watcher_delegate_.reset(
+ new ResolvConfWatcherDelegate(&resolv_conf_generation_, &lock_));
+ if (!resolv_conf_watcher_->Watch(
+ FilePath(FilePath::StringType(_PATH_RESCONF)),
+ resolv_conf_watcher_delegate_.get())) {
+ LOG(WARNING) << "Failed to install watcher for " << _PATH_RESCONF;
+ // We failed to install watcher, for whatever reason. Free the watcher.
+ resolv_conf_watcher_.reset();
+ resolv_conf_watcher_delegate_.reset();
+ } else {
+ LOG(INFO) << "Installed watcher for " << _PATH_RESCONF;
+ }
+}
+
+DnsReloadTimer::LocalState* DnsReloadTimer::GetLocalState() {
+ DnsReloadTimer::LocalState* state =
+ static_cast<DnsReloadTimer::LocalState*>(tls_index_.Get());
+ if (!state) {
+ state = new DnsReloadTimer::LocalState();
+ state->timer = base::TimeTicks::Now();
+ state->resolv_conf_generation = 0;
+ tls_index_.Set(state);
+ }
+ return state;
+}
+
// A TLS slot to the TimeTicks for the current thread.
// static
ThreadLocalStorage::Slot DnsReloadTimer::tls_index_(base::LINKER_INITIALIZED);
-base::LazyInstance<DnsReloadTimer,
- base::LeakyLazyInstanceTraits<DnsReloadTimer> >
- g_dns_reload_timer(base::LINKER_INITIALIZED);
+typedef base::LazyInstance<DnsReloadTimer,
+ base::LeakyLazyInstanceTraits<DnsReloadTimer> >
+ DnsReloadTimerInstance;
+DnsReloadTimerInstance g_dns_reload_timer(base::LINKER_INITIALIZED);
-} // namespace
+// This task is run on file thread
+// and calls DnsReloadTimer::InitResolvConfWatcher().
+class InitResolvConfWatcherTask : public Task {
+ public:
+ InitResolvConfWatcherTask(DnsReloadTimerInstance* dns_reload_timer_instance)
+ : dns_reload_timer_instance_(dns_reload_timer_instance) {
+ }
-namespace net {
+ virtual void Run() {
+ dns_reload_timer_instance_->Pointer()->InitResolvConfWatcher();
+ }
+ private:
+ DnsReloadTimerInstance* dns_reload_timer_instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(InitResolvConfWatcherTask);
+};
+
bool DnsReloadTimerHasExpired() {
DnsReloadTimer* dns_timer = g_dns_reload_timer.Pointer();
return dns_timer->Expired();
}
+bool ResolvConfUpdated() {
+ DnsReloadTimer* dns_timer = g_dns_reload_timer.Pointer();
+ return dns_timer->ResolvConfUpdated();
+}
+
+void InitResolvConfWatcher(base::Thread* file_thread) {
+ // FileWatcher must be used on the file thread.
+ // Additionally, we delay initialization - resolv.conf is read on first use
+ // anyway, this watcher will most likely be useful later.
+ file_thread->message_loop()->PostDelayedTask(
+ FROM_HERE, new InitResolvConfWatcherTask(&g_dns_reload_timer), 5000);
+}
+
} // namespace net
-#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
+#endif // WATCH_RESOLV_CONF
« no previous file with comments | « net/base/dns_reload_timer.h ('k') | net/base/dnsrr_resolver.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698