summaryrefslogtreecommitdiffstats
path: root/chrome/browser/net
diff options
context:
space:
mode:
authorericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-20 19:34:59 +0000
committerericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-20 19:34:59 +0000
commitaf9a7a5f59a1b5988b9c0e948c95724f61910393 (patch)
treee5126cb55ffa6349cfff360934f695d5fd151686 /chrome/browser/net
parentc67b2c02a50a32edb4ecebd1cd1c034549e43dfd (diff)
downloadchromium_src-af9a7a5f59a1b5988b9c0e948c95724f61910393.zip
chromium_src-af9a7a5f59a1b5988b9c0e948c95724f61910393.tar.gz
chromium_src-af9a7a5f59a1b5988b9c0e948c95724f61910393.tar.bz2
Check for NULL Profile::GetDefaultRequestContext().
This papers over a chrome-bot crash. The problem is that the ChromeURLRequestContexts have a split life between the UI thread and IO thread. Although conceptually they live on the IO thread, they are lazy-initialized on the UI thread, and are contained by a Profile which also lives on the UI thread. What happens in this crash, is ResolveProxyMsgHelper (the class which handles IPCs from the plugin process for proxy resolving) calls Profile::GetDefaultRequestContext() to get at the main URLRequestContext from the IO thread. Well, during the shutdown sequence, ~ProfileImpl NULLs the default request context before the IO thread is torn down, so consumers on the IO thread may get NULL. Or even worse, might get a non-NULL pointer to a request context that has already been freed. With this patch I hack past the NULL case. Really we need a proper solution to managing URLRequestContexts split personality... I did a quick survey of the code and found other consumers that use GetDefaultRequestContext from the IO thread, so this bug may be happening elsewhere. BUG=http://crbug.com/18358 Review URL: http://codereview.chromium.org/172085 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23854 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/net')
-rw-r--r--chrome/browser/net/resolve_proxy_msg_helper.cc28
-rw-r--r--chrome/browser/net/resolve_proxy_msg_helper.h11
2 files changed, 29 insertions, 10 deletions
diff --git a/chrome/browser/net/resolve_proxy_msg_helper.cc b/chrome/browser/net/resolve_proxy_msg_helper.cc
index d2f086f..90924d1 100644
--- a/chrome/browser/net/resolve_proxy_msg_helper.cc
+++ b/chrome/browser/net/resolve_proxy_msg_helper.cc
@@ -53,7 +53,16 @@ void ResolveProxyMsgHelper::StartPendingRequest() {
DCHECK(NULL == proxy_service_);
// Start the request.
- proxy_service_ = GetProxyService();
+ bool ok = GetProxyService(&proxy_service_);
+
+ if (!ok) {
+ // During shutdown, there may be no ProxyService to use, because the
+ // default ChromeURLRequestContext has already been NULL-ed out.
+ LOG(WARNING) << "Failed getting default URLRequestContext";
+ OnResolveProxyCompleted(net::ERR_FAILED);
+ return;
+ }
+
int result = proxy_service_->ResolveProxy(
req.url, &proxy_info_, &callback_, &req.pac_req, NULL);
@@ -62,13 +71,22 @@ void ResolveProxyMsgHelper::StartPendingRequest() {
OnResolveProxyCompleted(result);
}
-net::ProxyService* ResolveProxyMsgHelper::GetProxyService() const {
+bool ResolveProxyMsgHelper::GetProxyService(
+ scoped_refptr<net::ProxyService>* out) const {
// Unit-tests specify their own proxy service to use.
- if (proxy_service_override_)
- return proxy_service_override_;
+ if (proxy_service_override_) {
+ *out = proxy_service_override_;
+ return true;
+ }
+
+ // If there is no default request context (say during shut down).
+ URLRequestContext* context = Profile::GetDefaultRequestContext();
+ if (!context)
+ return false;
// Otherwise use the browser's global proxy service.
- return Profile::GetDefaultRequestContext()->proxy_service();
+ *out = context->proxy_service();
+ return true;
}
ResolveProxyMsgHelper::~ResolveProxyMsgHelper() {
diff --git a/chrome/browser/net/resolve_proxy_msg_helper.h b/chrome/browser/net/resolve_proxy_msg_helper.h
index edc74702..2bc03ec 100644
--- a/chrome/browser/net/resolve_proxy_msg_helper.h
+++ b/chrome/browser/net/resolve_proxy_msg_helper.h
@@ -43,13 +43,13 @@ class ResolveProxyMsgHelper {
virtual ~Delegate() {}
};
- // Construct a ResolveProxyMsgHelper instance that notifies request
+ // Constructs a ResolveProxyMsgHelper instance that notifies request
// completion to |delegate|. Note that |delegate| must be live throughout
// our lifespan. If |proxy_service| is NULL, then the current profile's
// proxy service will be used.
ResolveProxyMsgHelper(Delegate* delegate, net::ProxyService* proxy_service);
- // Resolve proxies for |url|. Completion is notified through the delegate.
+ // Resolves proxies for |url|. Completion is notified through the delegate.
// If multiple requests are started at the same time, they will run in
// FIFO order, with only 1 being outstanding at a time.
void Start(const GURL& url, IPC::Message* reply_msg);
@@ -62,11 +62,12 @@ class ResolveProxyMsgHelper {
// Callback for the ProxyService (bound to |callback_|).
void OnResolveProxyCompleted(int result);
- // Start the first pending request.
+ // Starts the first pending request.
void StartPendingRequest();
- // Get the proxy service instance to use.
- net::ProxyService* GetProxyService() const;
+ // Get the proxy service instance to use. On success returns true and
+ // sets |*out|. Otherwise returns false.
+ bool GetProxyService(scoped_refptr<net::ProxyService>* out) const;
// A PendingRequest is a resolve request that is in progress, or queued.
struct PendingRequest {