diff options
Diffstat (limited to 'chrome/gpu/gpu_main.cc')
-rw-r--r-- | chrome/gpu/gpu_main.cc | 89 |
1 files changed, 80 insertions, 9 deletions
diff --git a/chrome/gpu/gpu_main.cc b/chrome/gpu/gpu_main.cc index 9bd6568..5d0e090 100644 --- a/chrome/gpu/gpu_main.cc +++ b/chrome/gpu/gpu_main.cc @@ -4,6 +4,9 @@ #include <stdlib.h> +#include "app/app_switches.h" +#include "app/gfx/gl/gl_context.h" +#include "app/gfx/gl/gl_implementation.h" #include "app/win/scoped_com_initializer.h" #include "base/environment.h" #include "base/message_loop.h" @@ -17,6 +20,7 @@ #include "chrome/gpu/gpu_config.h" #include "chrome/gpu/gpu_process.h" #include "chrome/gpu/gpu_thread.h" +#include "chrome/gpu/gpu_watchdog_thread.h" #if defined(USE_LINUX_BREAKPAD) #include "chrome/app/breakpad_linux.h" @@ -24,12 +28,31 @@ #if defined(OS_MACOSX) #include "chrome/common/chrome_application_mac.h" +#include "chrome/common/sandbox_mac.h" #endif #if defined(USE_X11) #include "gfx/gtk_util.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 and windows. + return true; +#endif +} + +} // namespace + // Main function for starting the Gpu process. int GpuMain(const MainFunctionParams& parameters) { base::Time start_time = base::Time::Now(); @@ -63,21 +86,69 @@ int GpuMain(const MainFunctionParams& parameters) { gfx::GtkInitFromCommandLine(command_line); #endif - // 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. + // Note that kNoSandbox will also disable the GPU sandbox. + bool no_gpu_sandbox = command_line.HasSwitch(switches::kNoGpuSandbox); + if (!no_gpu_sandbox) { + if (!InitializeGpuSandbox()) { + LOG(ERROR) << "Failed to initialize the GPU sandbox"; + return EXIT_FAILURE; + } + } else { + LOG(ERROR) << "Running without GPU sandbox"; + } + + // 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::GLContext::InitializeOneOff()) + return EXIT_FAILURE; + + // Do this soon before running the message loop so accurate + // initialization time is recorded in the GPU info. Don't do it before + // starting the watchdog thread since it can take a significant amount of + // time to collect GPU information in GpuThread::Init. GpuProcess gpu_process; - GpuThread* gpu_thread = new GpuThread(command_line); + GpuThread* gpu_thread = new GpuThread; gpu_thread->Init(start_time); gpu_process.set_main_thread(gpu_thread); + + // 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 + // to run slowly in that case. + bool enable_watchdog = + !command_line.HasSwitch(switches::kDisableGpuWatchdog) && + gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL && + !RunningOnValgrind(); + + // Disable the watchdog in debug builds because they tend to only be run by + // developers who will not appreciate the watchdog killing the GPU process. +#ifndef NDEBUG + enable_watchdog = false; +#endif + + // Disable the watchdog for Windows. It tends to abort when the GPU process + // is not hung but still taking a long time to do something. Instead, the + // browser process displays a dialog when it notices that the child window + // is hung giving the user an opportunity to terminate it. This is the + // same mechanism used to abort hung plugins. +#if defined(OS_WIN) + enable_watchdog = false; +#endif + + // Start the GPU watchdog only after anything that is expected to be time + // consuming has completed, otherwise the process is liable to be aborted. + scoped_refptr<GpuWatchdogThread> watchdog_thread; + if (enable_watchdog) { + watchdog_thread = new GpuWatchdogThread(kGpuTimeout); + watchdog_thread->Start(); + } + main_message_loop.Run(); - gpu_thread->StopWatchdog(); + if (enable_watchdog) + watchdog_thread->Stop(); return 0; } |