summaryrefslogtreecommitdiffstats
path: root/net/proxy/proxy_resolver_js_bindings.cc
diff options
context:
space:
mode:
authoreroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-17 00:07:04 +0000
committereroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-17 00:07:04 +0000
commit1ca2b45a6e0b6490d0ab1ff940e2d7769660682b (patch)
treef6740d35ae7bf87007f6794a49f53f2858ead7b7 /net/proxy/proxy_resolver_js_bindings.cc
parent54ce726e1af62939cb12b09dc687737b114d426c (diff)
downloadchromium_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.cc100
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