diff options
author | kbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 18:13:28 +0000 |
---|---|---|
committer | kbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 18:13:28 +0000 |
commit | 0b2cec69a613d94f2ee72743ba53f539843e85e3 (patch) | |
tree | 8ed8627b2fd91716f11b16a5b8174b611f6b33c3 /content | |
parent | 638b1808f8c609dbf58c319837a78f1c316f82cd (diff) | |
download | chromium_src-0b2cec69a613d94f2ee72743ba53f539843e85e3.zip chromium_src-0b2cec69a613d94f2ee72743ba53f539843e85e3.tar.gz chromium_src-0b2cec69a613d94f2ee72743ba53f539843e85e3.tar.bz2 |
Initialize the sandbox earlier in GPU process bringup, deferring any
errors until receipt of the first IPC message.
Tested by running WebGL content with this patch on Mac and Windows.
BUG=84650
TEST=none
Review URL: http://codereview.chromium.org/7458009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93676 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/gpu/gpu_child_thread.cc | 69 | ||||
-rw-r--r-- | content/gpu/gpu_child_thread.h | 9 | ||||
-rw-r--r-- | content/gpu/gpu_main.cc | 46 |
3 files changed, 49 insertions, 75 deletions
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc index 62336cc..c854fb3 100644 --- a/content/gpu/gpu_child_thread.cc +++ b/content/gpu/gpu_child_thread.cc @@ -19,31 +19,11 @@ #include "content/gpu/gpu_watchdog_thread.h" #include "ipc/ipc_channel_handle.h" #include "ui/gfx/gl/gl_implementation.h" -#include "ui/gfx/gl/gl_surface.h" - -#if defined(OS_MACOSX) -#include "content/common/sandbox_init_wrapper.h" -#include "content/common/sandbox_mac.h" -#elif defined(OS_WIN) -#include "sandbox/src/sandbox.h" -#endif const int kGpuTimeout = 10000; namespace { -bool InitializeGpuSandbox() { -#if defined(OS_MACOSX) - CommandLine* parsed_command_line = CommandLine::ForCurrentProcess(); - SandboxInitWrapper sandbox_wrapper; - return sandbox_wrapper.InitializeSandbox(*parsed_command_line, - switches::kGpuProcess); -#else - // TODO(port): Create GPU sandbox for linux. - return true; -#endif -} - bool GpuProcessLogMessageHandler(int severity, const char* file, int line, size_t message_start, @@ -57,18 +37,16 @@ bool GpuProcessLogMessageHandler(int severity, } // namespace +GpuChildThread::GpuChildThread(bool dead_on_arrival) + : dead_on_arrival_(dead_on_arrival) { #if defined(OS_WIN) -GpuChildThread::GpuChildThread(sandbox::TargetServices* target_services) - : target_services_(target_services), - collecting_dx_diagnostics_(false) { -} -#else -GpuChildThread::GpuChildThread() { -} + collecting_dx_diagnostics_ = false; #endif +} GpuChildThread::GpuChildThread(const std::string& channel_id) - : ChildThread(channel_id) { + : ChildThread(channel_id), + dead_on_arrival_(false) { #if defined(OS_WIN) target_services_ = NULL; collecting_dx_diagnostics_ = false; @@ -112,20 +90,18 @@ bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) { } void GpuChildThread::OnInitialize() { + if (dead_on_arrival_) { + LOG(INFO) << "Exiting GPU process due to errors during initialization"; + MessageLoop::current()->Quit(); + return; + } + // We don't need to pipe log messages if we are running the GPU thread in // the browser process. if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) logging::SetLogMessageHandler(GpuProcessLogMessageHandler); - // Load the GL implementation and locate the bindings before starting the GPU - // watchdog because this can take a lot of time and the GPU watchdog might - // terminate the GPU process. - if (!gfx::GLSurface::InitializeOneOff()) { - LOG(INFO) << "GLContext::InitializeOneOff failed"; - MessageLoop::current()->Quit(); - return; - } gpu_info_collector::CollectGraphicsInfo(&gpu_info_); content::GetContentClient()->SetGpuInfo(gpu_info_); @@ -135,27 +111,6 @@ void GpuChildThread::OnInitialize() { // take a significant amount of time. gpu_info_.initialization_time = base::Time::Now() - process_start_time_; -#if defined (OS_MACOSX) - // Note that kNoSandbox will also disable the GPU sandbox. - bool no_gpu_sandbox = CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableGpuSandbox); - if (!no_gpu_sandbox) { - if (!InitializeGpuSandbox()) { - LOG(ERROR) << "Failed to initialize the GPU sandbox"; - MessageLoop::current()->Quit(); - return; - } - } else { - LOG(ERROR) << "Running without GPU sandbox"; - } -#elif defined(OS_WIN) - // For windows, if the target_services interface is not zero, the process - // is sandboxed and we must call LowerToken() before rendering untrusted - // content. - if (target_services_) - target_services_->LowerToken(); -#endif - // In addition to disabling the watchdog if the command line switch is // present, disable it in two other cases. OSMesa is expected to run very // slowly. Also disable the watchdog on valgrind because the code is expected diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h index 6fc8fbd..06643dc 100644 --- a/content/gpu/gpu_child_thread.h +++ b/content/gpu/gpu_child_thread.h @@ -38,11 +38,7 @@ class GpuWatchdogThread; // commands to the GPU. class GpuChildThread : public ChildThread { public: -#if defined(OS_WIN) - explicit GpuChildThread(sandbox::TargetServices* target_services); -#else - GpuChildThread(); -#endif + explicit GpuChildThread(bool dead_on_arrival); // For single-process mode. explicit GpuChildThread(const std::string& channel_id); @@ -69,6 +65,9 @@ class GpuChildThread : public ChildThread { static void SetDxDiagnostics(GpuChildThread* thread, const DxDiagNode& node); #endif + // Set this flag to true if a fatal error occurred before we receive the + // OnInitialize message, in which case we just declare ourselves DOA. + bool dead_on_arrival_; base::Time process_start_time_; scoped_refptr<GpuWatchdogThread> watchdog_thread_; diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc index cea11e6..1b0f58b 100644 --- a/content/gpu/gpu_main.cc +++ b/content/gpu/gpu_main.cc @@ -19,9 +19,12 @@ #include "content/common/main_function_params.h" #include "content/gpu/gpu_child_thread.h" #include "content/gpu/gpu_process.h" +#include "ui/gfx/gl/gl_surface.h" #if defined(OS_MACOSX) #include "content/common/chrome_application_mac.h" +#elif defined(OS_WIN) +#include "sandbox/src/sandbox.h" #endif #if defined(USE_X11) @@ -37,6 +40,35 @@ int GpuMain(const MainFunctionParams& parameters) { ChildProcess::WaitForDebugger("Gpu"); } + // Initialization of the OpenGL bindings may fail, in which case we + // will need to tear down this process. However, we can not do so + // safely until the IPC channel is set up, because the detection of + // early return of a child process is implemented using an IPC + // channel error. If the IPC channel is not fully set up between the + // browser and GPU process, and the GPU process crashes or exits + // early, the browser process will never detect it. For this reason + // we defer tearing down the GPU process until receiving the + // GpuMsg_Initialize message from the browser. + bool dead_on_arrival = false; + +#if defined(OS_WIN) + sandbox::TargetServices* target_services = + parameters.sandbox_info_.TargetServices(); + // For windows, if the target_services interface is not zero, the process + // is sandboxed and we must call LowerToken() before rendering untrusted + // content. + if (target_services) + target_services->LowerToken(); +#endif + + // Load the GL implementation and locate the bindings before starting the GPU + // watchdog because this can take a lot of time and the GPU watchdog might + // terminate the GPU process. + if (!gfx::GLSurface::InitializeOneOff()) { + LOG(INFO) << "GLContext::InitializeOneOff failed"; + dead_on_arrival = true; + } + #if defined(OS_MACOSX) chrome_application_mac::RegisterCrApp(); #endif @@ -59,21 +91,9 @@ int GpuMain(const MainFunctionParams& parameters) { base::win::ScopedCOMInitializer com_initializer; - // We can not tolerate early returns from this code, because the - // detection of early return of a child process is implemented using - // an IPC channel error. If the IPC channel is not fully set up - // between the browser and GPU process, and the GPU process crashes - // or exits early, the browser process will never detect it. For - // this reason we defer all work related to the GPU until receiving - // the GpuMsg_Initialize message from the browser. GpuProcess gpu_process; - GpuChildThread* child_thread = -#if defined(OS_WIN) - new GpuChildThread(parameters.sandbox_info_.TargetServices()); -#else - new GpuChildThread; -#endif + GpuChildThread* child_thread = new GpuChildThread(dead_on_arrival); child_thread->Init(start_time); |