summaryrefslogtreecommitdiffstats
path: root/net/base/network_change_notifier_win.cc
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-05 17:08:13 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-05 17:08:13 +0000
commitaab6693524a5303a9c41e5cd4f45808c82a3b01c (patch)
tree190d3a457f4030aad1b81f35b8c665865676d86b /net/base/network_change_notifier_win.cc
parentffa9030e06ad1a53141ef51493833b8019291217 (diff)
downloadchromium_src-aab6693524a5303a9c41e5cd4f45808c82a3b01c.zip
chromium_src-aab6693524a5303a9c41e5cd4f45808c82a3b01c.tar.gz
chromium_src-aab6693524a5303a9c41e5cd4f45808c82a3b01c.tar.bz2
Experimental workaround for CHECK in NetworkChangeNotifierWin.
Also adds a related UMA histogram. BUG=69198 TEST=NetworkChangeNotifierWinTest.*, UMA metrics Review URL: http://codereview.chromium.org/7886036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@104120 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/network_change_notifier_win.cc')
-rw-r--r--net/base/network_change_notifier_win.cc83
1 files changed, 75 insertions, 8 deletions
diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc
index 91d6ffb..590bfca 100644
--- a/net/base/network_change_notifier_win.cc
+++ b/net/base/network_change_notifier_win.cc
@@ -7,23 +7,36 @@
#include <iphlpapi.h>
#include <winsock2.h>
+#include "base/bind.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/time.h"
#include "net/base/winsock_init.h"
#pragma comment(lib, "iphlpapi.lib")
+namespace {
+
+// Time between NotifyAddrChange retries, on failure.
+const int kWatchForAddressChangeRetryIntervalMs = 500;
+
+} // namespace
+
namespace net {
-NetworkChangeNotifierWin::NetworkChangeNotifierWin() {
+NetworkChangeNotifierWin::NetworkChangeNotifierWin()
+ : is_watching_(false),
+ sequential_failures_(0),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
memset(&addr_overlapped_, 0, sizeof addr_overlapped_);
addr_overlapped_.hEvent = WSACreateEvent();
- WatchForAddressChange();
}
NetworkChangeNotifierWin::~NetworkChangeNotifierWin() {
- CancelIPChangeNotify(&addr_overlapped_);
- addr_watcher_.StopWatching();
+ if (is_watching_) {
+ CancelIPChangeNotify(&addr_overlapped_);
+ addr_watcher_.StopWatching();
+ }
WSACloseEvent(addr_overlapped_.hEvent);
}
@@ -145,6 +158,18 @@ bool NetworkChangeNotifierWin::IsCurrentlyOffline() const {
}
void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(is_watching_);
+ is_watching_ = false;
+
+ // Start watching for the next address change.
+ WatchForAddressChange();
+
+ NotifyObservers();
+}
+
+void NetworkChangeNotifierWin::NotifyObservers() {
+ DCHECK(CalledOnValidThread());
NotifyObserversOfIPAddressChange();
// Calling IsOffline() at this very moment is likely to give
@@ -155,16 +180,58 @@ void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) {
timer_.Stop(); // cancel any already waiting notification
timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this,
&NetworkChangeNotifierWin::NotifyParentOfOnlineStateChange);
-
- // Start watching for the next address change.
- WatchForAddressChange();
}
void NetworkChangeNotifierWin::WatchForAddressChange() {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!is_watching_);
+
+ // NotifyAddrChange occasionally fails with ERROR_OPEN_FAILED for unknown
+ // reasons. More rarely, it's also been observed failing with
+ // ERROR_NO_SYSTEM_RESOURCES. When either of these happens, we retry later.
+ if (!WatchForAddressChangeInternal()) {
+ ++sequential_failures_;
+
+ // TODO(mmenke): If the UMA histograms indicate that this fixes
+ // http://crbug.com/69198, remove this histogram and consider reducing the
+ // retry interval.
+ if (sequential_failures_ == 100) {
+ UMA_HISTOGRAM_COUNTS_100("Net.NotifyAddrChangeFailures",
+ sequential_failures_);
+ }
+
+ MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&NetworkChangeNotifierWin::WatchForAddressChange,
+ weak_factory_.GetWeakPtr()),
+ kWatchForAddressChangeRetryIntervalMs);
+ return;
+ }
+
+ // Treat the transition from NotifyAddrChange failing to succeeding as a
+ // network change event, since network changes were not being observed in
+ // that interval.
+ if (sequential_failures_ > 0)
+ NotifyObservers();
+
+ if (sequential_failures_ < 100) {
+ UMA_HISTOGRAM_COUNTS_100("Net.NotifyAddrChangeFailures",
+ sequential_failures_);
+ }
+
+ is_watching_ = true;
+ sequential_failures_ = 0;
+}
+
+bool NetworkChangeNotifierWin::WatchForAddressChangeInternal() {
+ DCHECK(CalledOnValidThread());
HANDLE handle = NULL;
DWORD ret = NotifyAddrChange(&handle, &addr_overlapped_);
- CHECK_EQ(static_cast<DWORD>(ERROR_IO_PENDING), ret);
+ if (ret != ERROR_IO_PENDING)
+ return false;
+
addr_watcher_.StartWatching(addr_overlapped_.hEvent, this);
+ return true;
}
void NetworkChangeNotifierWin::NotifyParentOfOnlineStateChange() {