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/proxy_resolver_js_bindings.cc | |
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/proxy_resolver_js_bindings.cc')
-rw-r--r-- | net/proxy/proxy_resolver_js_bindings.cc | 100 |
1 files changed, 12 insertions, 88 deletions
diff --git a/net/proxy/proxy_resolver_js_bindings.cc b/net/proxy/proxy_resolver_js_bindings.cc index 0906e7a..4703f2e 100644 --- a/net/proxy/proxy_resolver_js_bindings.cc +++ b/net/proxy/proxy_resolver_js_bindings.cc @@ -4,10 +4,7 @@ #include "net/proxy/proxy_resolver_js_bindings.h" -#include "base/compiler_specific.h" #include "base/logging.h" -#include "base/message_loop.h" -#include "base/waitable_event.h" #include "net/base/address_list.h" #include "net/base/host_resolver.h" #include "net/base/net_errors.h" @@ -18,85 +15,11 @@ namespace net { namespace { -// Wrapper around HostResolver to give a sync API while running the resolve -// in async mode on |host_resolver_loop|. If |host_resolver_loop| is NULL, -// runs sync on the current thread (this mode is just used by testing). -class SyncHostResolverBridge - : public base::RefCountedThreadSafe<SyncHostResolverBridge> { - public: - SyncHostResolverBridge(HostResolver* host_resolver, - MessageLoop* host_resolver_loop) - : host_resolver_(host_resolver), - host_resolver_loop_(host_resolver_loop), - event_(false, false), - ALLOW_THIS_IN_INITIALIZER_LIST( - callback_(this, &SyncHostResolverBridge::OnResolveCompletion)) { - } - - // Run the resolve on host_resolver_loop, and wait for result. - int Resolve(const std::string& hostname, - AddressFamily address_family, - net::AddressList* addresses) { - // Port number doesn't matter. - HostResolver::RequestInfo info(hostname, 80); - info.set_address_family(address_family); - - // Hack for tests -- run synchronously on current thread. - if (!host_resolver_loop_) - return host_resolver_->Resolve(info, addresses, NULL, NULL, - BoundNetLog()); - - // Otherwise start an async resolve on the resolver's thread. - host_resolver_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, - &SyncHostResolverBridge::StartResolve, info, addresses)); - - // Wait for the resolve to complete in the resolver's thread. - event_.Wait(); - return err_; - } - - private: - friend class base::RefCountedThreadSafe<SyncHostResolverBridge>; - - ~SyncHostResolverBridge() {} - - // Called on host_resolver_loop_. - void StartResolve(const HostResolver::RequestInfo& info, - net::AddressList* addresses) { - DCHECK_EQ(host_resolver_loop_, MessageLoop::current()); - int error = host_resolver_->Resolve( - info, addresses, &callback_, NULL, BoundNetLog()); - if (error != ERR_IO_PENDING) - OnResolveCompletion(error); // Completed synchronously. - } - - // Called on host_resolver_loop_. - void OnResolveCompletion(int result) { - DCHECK_EQ(host_resolver_loop_, MessageLoop::current()); - err_ = result; - event_.Signal(); - } - - 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 result request (set by in host_resolver_loop_). - int err_; -}; - // ProxyResolverJSBindings implementation. class DefaultJSBindings : public ProxyResolverJSBindings { public: - DefaultJSBindings(HostResolver* host_resolver, - MessageLoop* host_resolver_loop) - : host_resolver_(new SyncHostResolverBridge( - host_resolver, host_resolver_loop)) {} + explicit DefaultJSBindings(HostResolver* host_resolver) + : host_resolver_(host_resolver) {} // Handler for "alert(message)". virtual void Alert(const std::string& message) { @@ -124,10 +47,11 @@ class DefaultJSBindings : public ProxyResolverJSBindings { // Consequently a lot of existing PAC scripts assume they will only get // IPv4 results, and will misbehave if they get an IPv6 result. // See http://crbug.com/24641 for more details. + HostResolver::RequestInfo info(host, 80); // Port doesn't matter. + info.set_address_family(ADDRESS_FAMILY_IPV4); net::AddressList address_list; - int result = host_resolver_->Resolve(host, - ADDRESS_FAMILY_IPV4, - &address_list); + int result = host_resolver_->Resolve(info, &address_list, NULL, NULL, + BoundNetLog()); if (result != OK) return std::string(); // Failed. @@ -143,10 +67,10 @@ class DefaultJSBindings : public ProxyResolverJSBindings { // Handler for "dnsResolveEx(host)". Returns empty string on failure. virtual std::string DnsResolveEx(const std::string& host) { // Do a sync resolve of the hostname. + HostResolver::RequestInfo info(host, 80); // Port doesn't matter. net::AddressList address_list; - int result = host_resolver_->Resolve(host, - ADDRESS_FAMILY_UNSPECIFIED, - &address_list); + int result = host_resolver_->Resolve(info, &address_list, NULL, NULL, + BoundNetLog()); if (result != OK) return std::string(); // Failed. @@ -174,15 +98,15 @@ class DefaultJSBindings : public ProxyResolverJSBindings { } private: - scoped_refptr<SyncHostResolverBridge> host_resolver_; + scoped_refptr<HostResolver> host_resolver_; }; } // namespace // static ProxyResolverJSBindings* ProxyResolverJSBindings::CreateDefault( - HostResolver* host_resolver, MessageLoop* host_resolver_loop) { - return new DefaultJSBindings(host_resolver, host_resolver_loop); + HostResolver* host_resolver) { + return new DefaultJSBindings(host_resolver); } } // namespace net |