Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(749)

Side by Side Diff: content/browser/gpu/browser_gpu_channel_host_factory.cc

Issue 10852012: Fix lost context recreation race in BrowserGpuChannelHostFactory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/gpu/browser_gpu_channel_host_factory.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" 5 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/threading/thread_restrictions.h" 8 #include "base/threading/thread_restrictions.h"
9 #include "content/browser/gpu/gpu_data_manager_impl.h" 9 #include "content/browser/gpu/gpu_data_manager_impl.h"
10 #include "content/browser/gpu/gpu_process_host.h" 10 #include "content/browser/gpu/gpu_process_host.h"
11 #include "content/browser/gpu/gpu_surface_tracker.h" 11 #include "content/browser/gpu/gpu_surface_tracker.h"
12 #include "content/common/gpu/gpu_messages.h" 12 #include "content/common/gpu/gpu_messages.h"
13 #include "content/common/child_process_host_impl.h" 13 #include "content/common/child_process_host_impl.h"
14 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/common/content_client.h" 15 #include "content/public/common/content_client.h"
16 16
17 namespace content { 17 namespace content {
18 18
19 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL; 19 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
20 20
21 BrowserGpuChannelHostFactory::CreateRequest::CreateRequest() 21 BrowserGpuChannelHostFactory::CreateRequest::CreateRequest()
22 : event(false, false), 22 : event(false, false),
23 gpu_host_id(0),
23 route_id(MSG_ROUTING_NONE) { 24 route_id(MSG_ROUTING_NONE) {
24 } 25 }
25 26
26 BrowserGpuChannelHostFactory::CreateRequest::~CreateRequest() { 27 BrowserGpuChannelHostFactory::CreateRequest::~CreateRequest() {
27 } 28 }
28 29
29 BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest() 30 BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest(
30 : event(false, false) { 31 CauseForGpuLaunch cause)
32 : event(false, false),
33 cause_for_gpu_launch(cause),
34 gpu_host_id(0),
35 reused_gpu_process(true) {
31 } 36 }
32 37
33 BrowserGpuChannelHostFactory::EstablishRequest::~EstablishRequest() { 38 BrowserGpuChannelHostFactory::EstablishRequest::~EstablishRequest() {
34 } 39 }
35 40
36 void BrowserGpuChannelHostFactory::Initialize() { 41 void BrowserGpuChannelHostFactory::Initialize() {
37 instance_ = new BrowserGpuChannelHostFactory(); 42 instance_ = new BrowserGpuChannelHostFactory();
38 } 43 }
39 44
40 void BrowserGpuChannelHostFactory::Terminate() { 45 void BrowserGpuChannelHostFactory::Terminate() {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 // We're blocking the UI thread, which is generally undesirable. 128 // We're blocking the UI thread, which is generally undesirable.
124 // In this case we need to wait for this before we can show any UI /anyway/, 129 // In this case we need to wait for this before we can show any UI /anyway/,
125 // so it won't cause additional jank. 130 // so it won't cause additional jank.
126 // TODO(piman): Make this asynchronous (http://crbug.com/125248). 131 // TODO(piman): Make this asynchronous (http://crbug.com/125248).
127 base::ThreadRestrictions::ScopedAllowWait allow_wait; 132 base::ThreadRestrictions::ScopedAllowWait allow_wait;
128 request.event.Wait(); 133 request.event.Wait();
129 return request.route_id; 134 return request.route_id;
130 } 135 }
131 136
132 void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO( 137 void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO(
133 EstablishRequest* request, 138 EstablishRequest* request) {
134 CauseForGpuLaunch cause_for_gpu_launch) {
135 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); 139 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
136 if (!host) { 140 if (!host) {
137 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, 141 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
138 cause_for_gpu_launch); 142 request->cause_for_gpu_launch);
139 if (!host) { 143 if (!host) {
140 request->event.Signal(); 144 request->event.Signal();
141 return; 145 return;
142 } 146 }
143 gpu_host_id_ = host->host_id(); 147 gpu_host_id_ = host->host_id();
148 request->reused_gpu_process = false;
149 } else {
150 if (host->host_id() == request->gpu_host_id) {
151 // We come here if we retried to establish the channel because of a
152 // failure in GpuChannelEstablishedOnIO, but we ended up with the same
153 // process ID, meaning the failure was not because of a channel error, but
154 // another reason. So fail now.
155 request->event.Signal();
156 return;
157 }
158 request->reused_gpu_process = true;
144 } 159 }
160 request->gpu_host_id = gpu_host_id_;
145 161
146 host->EstablishGpuChannel( 162 host->EstablishGpuChannel(
147 gpu_client_id_, 163 gpu_client_id_,
148 true, 164 true,
149 base::Bind(&BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO, 165 base::Bind(&BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO,
166 base::Unretained(this),
150 request)); 167 request));
151 } 168 }
152 169
153 // static
154 void BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO( 170 void BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO(
155 EstablishRequest* request, 171 EstablishRequest* request,
156 const IPC::ChannelHandle& channel_handle, 172 const IPC::ChannelHandle& channel_handle,
157 const GPUInfo& gpu_info) { 173 const GPUInfo& gpu_info) {
158 request->channel_handle = channel_handle; 174 if (channel_handle.name.empty() && request->reused_gpu_process) {
159 request->gpu_info = gpu_info; 175 // We failed after re-using the GPU process, but it may have died in the
160 request->event.Signal(); 176 // mean time. Retry to have a chance to create a fresh GPU process.
177 EstablishGpuChannelOnIO(request);
178 } else {
179 request->channel_handle = channel_handle;
180 request->gpu_info = gpu_info;
181 request->event.Signal();
182 }
161 } 183 }
162 184
163 GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync( 185 GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
164 CauseForGpuLaunch cause_for_gpu_launch) { 186 CauseForGpuLaunch cause_for_gpu_launch) {
165 if (gpu_channel_.get()) { 187 if (gpu_channel_.get()) {
166 // Recreate the channel if it has been lost. 188 // Recreate the channel if it has been lost.
167 if (gpu_channel_->state() == GpuChannelHost::kLost) 189 if (gpu_channel_->state() == GpuChannelHost::kLost)
168 gpu_channel_ = NULL; 190 gpu_channel_ = NULL;
169 else 191 else
170 return gpu_channel_.get(); 192 return gpu_channel_.get();
171 } 193 }
172 // Ensure initialization on the main thread. 194 // Ensure initialization on the main thread.
173 GpuDataManagerImpl::GetInstance(); 195 GpuDataManagerImpl::GetInstance();
174 196
175 EstablishRequest request; 197 EstablishRequest request(cause_for_gpu_launch);
176 GetIOLoopProxy()->PostTask( 198 GetIOLoopProxy()->PostTask(
177 FROM_HERE, 199 FROM_HERE,
178 base::Bind( 200 base::Bind(
179 &BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO, 201 &BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO,
180 base::Unretained(this), 202 base::Unretained(this),
181 &request, 203 &request));
182 cause_for_gpu_launch));
183 204
184 { 205 {
185 // We're blocking the UI thread, which is generally undesirable. 206 // We're blocking the UI thread, which is generally undesirable.
186 // In this case we need to wait for this before we can show any UI /anyway/, 207 // In this case we need to wait for this before we can show any UI /anyway/,
187 // so it won't cause additional jank. 208 // so it won't cause additional jank.
188 // TODO(piman): Make this asynchronous (http://crbug.com/125248). 209 // TODO(piman): Make this asynchronous (http://crbug.com/125248).
189 base::ThreadRestrictions::ScopedAllowWait allow_wait; 210 base::ThreadRestrictions::ScopedAllowWait allow_wait;
190 request.event.Wait(); 211 request.event.Wait();
191 } 212 }
192 213
193 if (request.channel_handle.name.empty()) 214 if (request.channel_handle.name.empty())
194 return NULL; 215 return NULL;
195 216
196 gpu_channel_ = new GpuChannelHost(this, gpu_host_id_, gpu_client_id_); 217 gpu_channel_ = new GpuChannelHost(this, request.gpu_host_id, gpu_client_id_);
197 gpu_channel_->set_gpu_info(request.gpu_info); 218 gpu_channel_->set_gpu_info(request.gpu_info);
198 content::GetContentClient()->SetGpuInfo(request.gpu_info); 219 content::GetContentClient()->SetGpuInfo(request.gpu_info);
199 220
200 // Connect to the GPU process if a channel name was received. 221 // Connect to the GPU process if a channel name was received.
201 gpu_channel_->Connect(request.channel_handle); 222 gpu_channel_->Connect(request.channel_handle);
202 223
203 return gpu_channel_.get(); 224 return gpu_channel_.get();
204 } 225 }
205 226
206 } // namespace content 227 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/gpu/browser_gpu_channel_host_factory.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698