summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-03 21:00:14 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-03 21:00:14 +0000
commit1ac6af94287a2f821a43003b2be2ba21f319a66d (patch)
tree3398fd0b22e8f9bde49f5aa7f50ff3ab1a42a81c /net
parentcc204b2cfb421e72bb9d6187fa88cb412576fc94 (diff)
downloadchromium_src-1ac6af94287a2f821a43003b2be2ba21f319a66d.zip
chromium_src-1ac6af94287a2f821a43003b2be2ba21f319a66d.tar.gz
chromium_src-1ac6af94287a2f821a43003b2be2ba21f319a66d.tar.bz2
Make HostResolver NonThreadSafe and not thread safe refcounted.
Required making SyncHostResolverBridge not use RefCountedThreadSafe. I refactored the innards to have a thread safe refcounted Core implementation. BUG=45298 Review URL: http://codereview.chromium.org/2122015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48867 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/host_resolver.h4
-rw-r--r--net/base/host_resolver_impl.cc9
-rw-r--r--net/base/host_resolver_impl.h2
-rw-r--r--net/proxy/sync_host_resolver_bridge.cc189
-rw-r--r--net/proxy/sync_host_resolver_bridge.h38
-rw-r--r--net/proxy/sync_host_resolver_bridge_unittest.cc62
6 files changed, 183 insertions, 121 deletions
diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h
index e4bf847..d798688 100644
--- a/net/base/host_resolver.h
+++ b/net/base/host_resolver.h
@@ -32,7 +32,7 @@ class NetworkChangeNotifier;
// request at a time is to create a SingleRequestHostResolver wrapper around
// HostResolver (which will automatically cancel the single request when it
// goes out of scope).
-class HostResolver : public base::RefCountedThreadSafe<HostResolver> {
+class HostResolver : public base::RefCounted<HostResolver> {
public:
// The parameters for doing a Resolve(). |hostname| and |port| are required,
// the rest are optional (and have reasonable defaults).
@@ -179,7 +179,7 @@ class HostResolver : public base::RefCountedThreadSafe<HostResolver> {
virtual HostResolverImpl* GetAsHostResolverImpl() { return NULL; }
protected:
- friend class base::RefCountedThreadSafe<HostResolver>;
+ friend class base::RefCounted<HostResolver>;
HostResolver() { }
diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc
index 1f89af4..f3bc5c1 100644
--- a/net/base/host_resolver_impl.cc
+++ b/net/base/host_resolver_impl.cc
@@ -755,6 +755,8 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
CompletionCallback* callback,
RequestHandle* out_req,
const BoundNetLog& net_log) {
+ DCHECK(CalledOnValidThread());
+
if (shutdown_)
return ERR_UNEXPECTED;
@@ -840,6 +842,7 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
// See OnJobComplete(Job*) for why it is important not to clean out
// cancelled requests from Job::requests_.
void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
+ DCHECK(CalledOnValidThread());
if (shutdown_) {
// TODO(eroman): temp hack for: http://crbug.com/18373
// Because we destroy outstanding requests during Shutdown(),
@@ -869,10 +872,12 @@ void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
}
void HostResolverImpl::AddObserver(HostResolver::Observer* observer) {
+ DCHECK(CalledOnValidThread());
observers_.push_back(observer);
}
void HostResolverImpl::RemoveObserver(HostResolver::Observer* observer) {
+ DCHECK(CalledOnValidThread());
ObserversList::iterator it =
std::find(observers_.begin(), observers_.end(), observer);
@@ -883,18 +888,21 @@ void HostResolverImpl::RemoveObserver(HostResolver::Observer* observer) {
}
void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) {
+ DCHECK(CalledOnValidThread());
ipv6_probe_monitoring_ = false;
DiscardIPv6ProbeJob();
default_address_family_ = address_family;
}
void HostResolverImpl::ProbeIPv6Support() {
+ DCHECK(CalledOnValidThread());
DCHECK(!ipv6_probe_monitoring_);
ipv6_probe_monitoring_ = true;
OnIPAddressChanged(); // Give initial setup call.
}
void HostResolverImpl::Shutdown() {
+ DCHECK(CalledOnValidThread());
shutdown_ = true;
// Cancel the outstanding jobs.
@@ -907,6 +915,7 @@ void HostResolverImpl::Shutdown() {
void HostResolverImpl::SetPoolConstraints(JobPoolIndex pool_index,
size_t max_outstanding_jobs,
size_t max_pending_requests) {
+ DCHECK(CalledOnValidThread());
CHECK_GE(pool_index, 0);
CHECK_LT(pool_index, POOL_COUNT);
CHECK(jobs_.empty()) << "Can only set constraints during setup";
diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h
index 417cc77..a0e34ca 100644
--- a/net/base/host_resolver_impl.h
+++ b/net/base/host_resolver_impl.h
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "base/non_thread_safe.h"
#include "base/scoped_ptr.h"
#include "net/base/capturing_net_log.h"
#include "net/base/host_cache.h"
@@ -49,6 +50,7 @@ namespace net {
// Requests are ordered in the queue based on their priority.
class HostResolverImpl : public HostResolver,
+ public NonThreadSafe,
public NetworkChangeNotifier::Observer {
public:
// The index into |job_pools_| for the various job pools. Pools with a higher
diff --git a/net/proxy/sync_host_resolver_bridge.cc b/net/proxy/sync_host_resolver_bridge.cc
index 31a326d..caf4549 100644
--- a/net/proxy/sync_host_resolver_bridge.cc
+++ b/net/proxy/sync_host_resolver_bridge.cc
@@ -6,50 +6,123 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/lock.h"
#include "base/message_loop.h"
+#include "base/waitable_event.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
namespace net {
-// SyncHostResolverBridge -----------------------------------------------------
+// SyncHostResolverBridge::Core ----------------------------------------------
-SyncHostResolverBridge::SyncHostResolverBridge(HostResolver* host_resolver,
- MessageLoop* host_resolver_loop)
+class SyncHostResolverBridge::Core
+ : public base::RefCountedThreadSafe<SyncHostResolverBridge::Core> {
+ public:
+ Core(HostResolver* resolver, MessageLoop* host_resolver_loop);
+
+ int ResolveSynchronously(const HostResolver::RequestInfo& info,
+ AddressList* addresses);
+
+ // Returns true if Shutdown() has been called.
+ bool HasShutdown() const {
+ AutoLock l(lock_);
+ return HasShutdownLocked();
+ }
+
+ // Called on |host_resolver_loop_|.
+ void Shutdown();
+
+ private:
+ friend class base::RefCountedThreadSafe<SyncHostResolverBridge::Core>;
+
+ bool HasShutdownLocked() const {
+ return has_shutdown_;
+ }
+
+ // Called on |host_resolver_loop_|.
+ void StartResolve(const HostResolver::RequestInfo& info,
+ AddressList* addresses);
+
+ // Called on |host_resolver_loop_|.
+ void OnResolveCompletion(int result);
+
+ // Not called on |host_resolver_loop_|.
+ int WaitForResolveCompletion();
+
+ const scoped_refptr<HostResolver> host_resolver_;
+ MessageLoop* const host_resolver_loop_;
+ net::CompletionCallbackImpl<Core> callback_;
+ // The result from the current request (set on |host_resolver_loop_|).
+ int err_;
+ // The currently outstanding request to |host_resolver_|, or NULL.
+ HostResolver::RequestHandle outstanding_request_;
+
+ // Event to notify completion of resolve request. We always Signal() on
+ // |host_resolver_loop_| and Wait() on a different thread.
+ base::WaitableEvent event_;
+
+ // True if Shutdown() has been called. Must hold |lock_| to access it.
+ bool has_shutdown_;
+
+ // Mutex to guard accesses to |has_shutdown_|.
+ mutable Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(Core);
+};
+
+SyncHostResolverBridge::Core::Core(HostResolver* host_resolver,
+ MessageLoop* host_resolver_loop)
: host_resolver_(host_resolver),
host_resolver_loop_(host_resolver_loop),
- event_(true, false),
ALLOW_THIS_IN_INITIALIZER_LIST(
- callback_(this, &SyncHostResolverBridge::OnResolveCompletion)),
+ callback_(this, &Core::OnResolveCompletion)),
+ err_(0),
outstanding_request_(NULL),
- has_shutdown_(false) {
- DCHECK(host_resolver_loop_);
-}
-
-SyncHostResolverBridge::~SyncHostResolverBridge() {
- DCHECK(HasShutdown());
-}
-
-int SyncHostResolverBridge::Resolve(const RequestInfo& info,
- AddressList* addresses,
- CompletionCallback* callback,
- RequestHandle* out_req,
- const BoundNetLog& net_log) {
- DCHECK(!callback);
- DCHECK(!out_req);
+ event_(true, false),
+ has_shutdown_(false) {}
+int SyncHostResolverBridge::Core::ResolveSynchronously(
+ const HostResolver::RequestInfo& info,
+ net::AddressList* addresses) {
// Otherwise start an async resolve on the resolver's thread.
host_resolver_loop_->PostTask(
FROM_HERE,
- NewRunnableMethod(this, &SyncHostResolverBridge::StartResolve,
+ NewRunnableMethod(this, &Core::StartResolve,
info, addresses));
- // Wait for the resolve to complete in the resolver's thread.
+ return WaitForResolveCompletion();
+}
+
+void SyncHostResolverBridge::Core::StartResolve(
+ const HostResolver::RequestInfo& info,
+ net::AddressList* addresses) {
+ DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);
+ DCHECK(!outstanding_request_);
+
+ if (HasShutdown())
+ return;
+
+ int error = host_resolver_->Resolve(
+ info, addresses, &callback_, &outstanding_request_, BoundNetLog());
+ if (error != ERR_IO_PENDING)
+ OnResolveCompletion(error); // Completed synchronously.
+}
+
+void SyncHostResolverBridge::Core::OnResolveCompletion(int result) {
+ DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);
+ err_ = result;
+ outstanding_request_ = NULL;
+ event_.Signal();
+}
+
+int SyncHostResolverBridge::Core::WaitForResolveCompletion() {
+ DCHECK_NE(MessageLoop::current(), host_resolver_loop_);
event_.Wait();
{
AutoLock l(lock_);
- if (has_shutdown_)
+ if (HasShutdownLocked())
return ERR_ABORTED;
event_.Reset();
}
@@ -57,19 +130,7 @@ int SyncHostResolverBridge::Resolve(const RequestInfo& info,
return err_;
}
-void SyncHostResolverBridge::CancelRequest(RequestHandle req) {
- NOTREACHED();
-}
-
-void SyncHostResolverBridge::AddObserver(Observer* observer) {
- NOTREACHED();
-}
-
-void SyncHostResolverBridge::RemoveObserver(Observer* observer) {
- NOTREACHED();
-}
-
-void SyncHostResolverBridge::Shutdown() {
+void SyncHostResolverBridge::Core::Shutdown() {
DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);
if (outstanding_request_) {
@@ -77,32 +138,54 @@ void SyncHostResolverBridge::Shutdown() {
outstanding_request_ = NULL;
}
- AutoLock l(lock_);
- has_shutdown_ = true;
+ {
+ AutoLock l(lock_);
+ has_shutdown_ = true;
+ }
// Wake up the PAC thread in case it was waiting for resolve completion.
event_.Signal();
}
-void SyncHostResolverBridge::StartResolve(const HostResolver::RequestInfo& info,
- net::AddressList* addresses) {
- DCHECK_EQ(host_resolver_loop_, MessageLoop::current());
- DCHECK(!outstanding_request_);
+// SyncHostResolverBridge -----------------------------------------------------
- if (HasShutdown())
- return;
+SyncHostResolverBridge::SyncHostResolverBridge(HostResolver* host_resolver,
+ MessageLoop* host_resolver_loop)
+ : host_resolver_loop_(host_resolver_loop),
+ core_(new Core(host_resolver, host_resolver_loop)) {
+ DCHECK(host_resolver_loop_);
+}
- int error = host_resolver_->Resolve(
- info, addresses, &callback_, &outstanding_request_, BoundNetLog());
- if (error != ERR_IO_PENDING)
- OnResolveCompletion(error); // Completed synchronously.
+SyncHostResolverBridge::~SyncHostResolverBridge() {
+ DCHECK(core_->HasShutdown());
}
-void SyncHostResolverBridge::OnResolveCompletion(int result) {
- DCHECK_EQ(host_resolver_loop_, MessageLoop::current());
- err_ = result;
- outstanding_request_ = NULL;
- event_.Signal();
+int SyncHostResolverBridge::Resolve(const RequestInfo& info,
+ AddressList* addresses,
+ CompletionCallback* callback,
+ RequestHandle* out_req,
+ const BoundNetLog& net_log) {
+ DCHECK(!callback);
+ DCHECK(!out_req);
+
+ return core_->ResolveSynchronously(info, addresses);
+}
+
+void SyncHostResolverBridge::CancelRequest(RequestHandle req) {
+ NOTREACHED();
+}
+
+void SyncHostResolverBridge::AddObserver(Observer* observer) {
+ NOTREACHED();
+}
+
+void SyncHostResolverBridge::RemoveObserver(Observer* observer) {
+ NOTREACHED();
+}
+
+void SyncHostResolverBridge::Shutdown() {
+ DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);
+ core_->Shutdown();
}
// SingleThreadedProxyResolverUsingBridgedHostResolver -----------------------
diff --git a/net/proxy/sync_host_resolver_bridge.h b/net/proxy/sync_host_resolver_bridge.h
index d082043..4d25b4d 100644
--- a/net/proxy/sync_host_resolver_bridge.h
+++ b/net/proxy/sync_host_resolver_bridge.h
@@ -5,9 +5,7 @@
#ifndef NET_PROXY_SYNC_HOST_RESOLVER_BRIDGE_H_
#define NET_PROXY_SYNC_HOST_RESOLVER_BRIDGE_H_
-#include "base/lock.h"
#include "base/scoped_ptr.h"
-#include "base/waitable_event.h"
#include "net/base/host_resolver.h"
#include "net/proxy/single_threaded_proxy_resolver.h"
@@ -40,39 +38,10 @@ class SyncHostResolverBridge : public HostResolver {
void Shutdown();
private:
- // Called on |host_resolver_loop_|.
- void StartResolve(const HostResolver::RequestInfo& info,
- net::AddressList* addresses);
+ class Core;
- // Called on |host_resolver_loop_|.
- void OnResolveCompletion(int result);
-
- // Returns true if Shutdown() has been called.
- bool HasShutdown() const {
- AutoLock l(lock_);
- return has_shutdown_;
- }
-
- scoped_refptr<HostResolver> host_resolver_;
- MessageLoop* host_resolver_loop_;
-
- // Event to notify completion of resolve request.
- base::WaitableEvent event_;
-
- // Callback for when the resolve completes on host_resolver_loop_.
- net::CompletionCallbackImpl<SyncHostResolverBridge> callback_;
-
- // The result from the current request (set on |host_resolver_loop_|).
- int err_;
-
- // The currently outstanding request to |host_resolver_|, or NULL.
- HostResolver::RequestHandle outstanding_request_;
-
- // True if Shutdown() has been called. Must hold |lock_| to access it.
- bool has_shutdown_;
-
- // Mutex to guard accesses to |has_shutdown_|.
- mutable Lock lock_;
+ MessageLoop* const host_resolver_loop_;
+ scoped_refptr<Core> core_;
};
// Subclass of SingleThreadedProxyResolver that additionally calls
@@ -94,4 +63,3 @@ class SingleThreadedProxyResolverUsingBridgedHostResolver
} // namespace net
#endif // NET_PROXY_SYNC_HOST_RESOLVER_BRIDGE_H_
-
diff --git a/net/proxy/sync_host_resolver_bridge_unittest.cc b/net/proxy/sync_host_resolver_bridge_unittest.cc
index 916252b..42dbacc 100644
--- a/net/proxy/sync_host_resolver_bridge_unittest.cc
+++ b/net/proxy/sync_host_resolver_bridge_unittest.cc
@@ -5,6 +5,7 @@
#include "net/proxy/sync_host_resolver_bridge.h"
#include "base/thread.h"
+#include "base/waitable_event.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
@@ -116,16 +117,20 @@ class SyncProxyResolver : public ProxyResolver {
// network stack.
class IOThread : public base::Thread {
public:
- explicit IOThread(HostResolver* async_resolver)
- : base::Thread("IO-thread"), async_resolver_(async_resolver) {
- }
+ IOThread() : base::Thread("IO-thread") {}
virtual ~IOThread() {
Stop();
}
+ const scoped_refptr<BlockableHostResolver>& async_resolver() {
+ return async_resolver_;
+ }
+
protected:
virtual void Init() {
+ async_resolver_ = new BlockableHostResolver();
+
// Create a synchronous host resolver that operates the async host
// resolver on THIS thread.
scoped_refptr<SyncHostResolverBridge> sync_resolver =
@@ -149,10 +154,19 @@ class IOThread : public base::Thread {
// Delete the single threaded proxy resolver.
proxy_resolver_.reset();
+
+ // During the teardown sequence of the single threaded proxy resolver,
+ // the outstanding host resolve should have been cancelled.
+ EXPECT_TRUE(async_resolver_->was_request_cancelled());
+
+ async_resolver_ = NULL;
}
private:
- HostResolver* async_resolver_;
+ // This (async) host resolver will outlive the thread that is operating it
+ // synchronously.
+ scoped_refptr<BlockableHostResolver> async_resolver_;
+
scoped_ptr<ProxyResolver> proxy_resolver_;
// Data for the outstanding request to the single threaded proxy resolver.
@@ -165,35 +179,21 @@ class IOThread : public base::Thread {
// is outstanding on the SyncHostResolverBridge.
// This is a regression test for http://crbug.com/41244.
TEST(SingleThreadedProxyResolverWithBridgedHostResolverTest, ShutdownDeadlock) {
- // This (async) host resolver will outlive the thread that is operating it
- // synchronously.
- scoped_refptr<BlockableHostResolver> host_resolver =
- new BlockableHostResolver();
-
- {
- IOThread io_thread(host_resolver.get());
- base::Thread::Options options;
- options.message_loop_type = MessageLoop::TYPE_IO;
- ASSERT_TRUE(io_thread.StartWithOptions(options));
-
- // Wait until the host resolver receives a request (this means that the
- // PAC thread is now blocked, waiting for the async response from the
- // host resolver.
- host_resolver->WaitUntilRequestIsReceived();
-
- // Now upon exitting this scope, the IOThread is destroyed -- this will
- // stop the IOThread, which will in turn delete the
- // SingleThreadedProxyResolver, which in turn will stop its internal
- // PAC thread (which is currently blocked waiting on the host resolve which
- // is running on IOThread).
- }
-
- // During the teardown sequence of the single threaded proxy resolver,
- // the outstanding host resolve should have been cancelled.
- EXPECT_TRUE(host_resolver->was_request_cancelled());
+ IOThread io_thread;
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ ASSERT_TRUE(io_thread.StartWithOptions(options));
+
+ io_thread.async_resolver()->WaitUntilRequestIsReceived();
+
+ // Now upon exitting this scope, the IOThread is destroyed -- this will
+ // stop the IOThread, which will in turn delete the
+ // SingleThreadedProxyResolver, which in turn will stop its internal
+ // PAC thread (which is currently blocked waiting on the host resolve which
+ // is running on IOThread). The IOThread::Cleanup() will verify that after
+ // the PAC thread is stopped, it cancels the request on the HostResolver.
}
} // namespace
} // namespace net
-