summaryrefslogtreecommitdiffstats
path: root/chrome/gpu/gpu_main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/gpu/gpu_main.cc')
-rw-r--r--chrome/gpu/gpu_main.cc89
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;
}