diff options
author | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-17 00:07:04 +0000 |
---|---|---|
committer | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-17 00:07:04 +0000 |
commit | 1ca2b45a6e0b6490d0ab1ff940e2d7769660682b (patch) | |
tree | f6740d35ae7bf87007f6794a49f53f2858ead7b7 /net/proxy/sync_host_resolver_bridge.h | |
parent | 54ce726e1af62939cb12b09dc687737b114d426c (diff) | |
download | chromium_src-1ca2b45a6e0b6490d0ab1ff940e2d7769660682b.zip chromium_src-1ca2b45a6e0b6490d0ab1ff940e2d7769660682b.tar.gz chromium_src-1ca2b45a6e0b6490d0ab1ff940e2d7769660682b.tar.bz2 |
Fix a deadlock that could happen during shutdown if a host resolve request was outstanding by a PAC script.
The solution is to abort the oustanding host resolver request during shutdown, and wake-up the blocked PAC thread.
BUG=41244
TEST=SingleThreadedProxyResolverWithBridgedHostResolverTest.ShutdownDeadlock
Review URL: http://codereview.chromium.org/1527037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44864 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/proxy/sync_host_resolver_bridge.h')
-rw-r--r-- | net/proxy/sync_host_resolver_bridge.h | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/net/proxy/sync_host_resolver_bridge.h b/net/proxy/sync_host_resolver_bridge.h new file mode 100644 index 0000000..d082043 --- /dev/null +++ b/net/proxy/sync_host_resolver_bridge.h @@ -0,0 +1,97 @@ +// 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. + +#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" + +class MessageLoop; + +namespace net { + +// Wrapper around HostResolver to give a sync API while running the resolver +// in async mode on |host_resolver_loop|. +class SyncHostResolverBridge : public HostResolver { + public: + SyncHostResolverBridge(HostResolver* host_resolver, + MessageLoop* host_resolver_loop); + + virtual ~SyncHostResolverBridge(); + + // HostResolver methods: + virtual int Resolve(const RequestInfo& info, + AddressList* addresses, + CompletionCallback* callback, + RequestHandle* out_req, + const BoundNetLog& net_log); + virtual void CancelRequest(RequestHandle req); + virtual void AddObserver(Observer* observer); + virtual void RemoveObserver(Observer* observer); + + // The Shutdown() method should be called prior to destruction, from + // |host_resolver_loop_|. It aborts any in progress synchronous resolves, to + // prevent deadlocks from happening. + void Shutdown(); + + private: + // Called on |host_resolver_loop_|. + void StartResolve(const HostResolver::RequestInfo& info, + net::AddressList* addresses); + + // 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_; +}; + +// Subclass of SingleThreadedProxyResolver that additionally calls +// |bridged_host_resolver_->Shutdown()| during its destructor. +class SingleThreadedProxyResolverUsingBridgedHostResolver + : public SingleThreadedProxyResolver { + public: + SingleThreadedProxyResolverUsingBridgedHostResolver( + ProxyResolver* proxy_resolver, + SyncHostResolverBridge* bridged_host_resolver); + + virtual ~SingleThreadedProxyResolverUsingBridgedHostResolver(); + + private: + scoped_refptr<SyncHostResolverBridge> bridged_host_resolver_; +}; + + +} // namespace net + +#endif // NET_PROXY_SYNC_HOST_RESOLVER_BRIDGE_H_ + |