diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-20 19:34:59 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-20 19:34:59 +0000 |
commit | af9a7a5f59a1b5988b9c0e948c95724f61910393 (patch) | |
tree | e5126cb55ffa6349cfff360934f695d5fd151686 /chrome/browser/net | |
parent | c67b2c02a50a32edb4ecebd1cd1c034549e43dfd (diff) | |
download | chromium_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.cc | 28 | ||||
-rw-r--r-- | chrome/browser/net/resolve_proxy_msg_helper.h | 11 |
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 { |