- Relanding 61718.
I disabled the GPU watchdog in three new cases:
- If the OSMesa software renderer is in use. This will disable it on bots.
- When running on valgrind, whether on a bot or locally.
- In debug builds
I added a GPU process initialization time to the GPU info.
I moved the GPU initialization code outside the watchdog protection because it
can take a long time and trigger the watchdog.
I increased the timeout. I set up a field trial with different timeouts to see
the rate of failure for each period.
Original CL description:
I added a watchdog thread that intermitently checks the main thread can respond
to tasks posted on its message queue.
I fixed some bugs that prevented GGL from failing when the GPU channel was
lost.
Added a command line swith to disable the watchdog thread for debugging
purposes.
TEST=try, local testing of all features
BUG=none
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65461 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/gpu/gpu_main.cc b/chrome/gpu/gpu_main.cc
index b6dfef5..cf5822d4 100644
--- a/chrome/gpu/gpu_main.cc
+++ b/chrome/gpu/gpu_main.cc
@@ -2,16 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <stdlib.h>
+
#include "app/app_switches.h"
+#include "app/gfx/gl/gl_context.h"
#include "app/gfx/gl/gl_implementation.h"
+#include "base/environment.h"
#include "base/message_loop.h"
+#include "base/metrics/field_trial.h"
+#include "base/stringprintf.h"
#include "build/build_config.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/env_vars.h"
#include "chrome/common/main_function_params.h"
#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"
@@ -26,9 +34,17 @@
#include "app/x11_util_internal.h"
#endif
-#if defined(USE_X11)
+
namespace {
+// 1% per watchdog trial group.
+const int kFieldTrialSize = 1;
+
+// 5 - 20 seconds timeout.
+const int kMinGpuTimeout = 5;
+const int kMaxGpuTimeout = 20;
+
+#if defined(USE_X11)
int GpuX11ErrorHandler(Display* d, XErrorEvent* error) {
LOG(ERROR) << x11_util::GetErrorEventDescription(d, error);
return 0;
@@ -38,12 +54,14 @@
// Set up the error handlers so that only general errors aren't fatal.
x11_util::SetX11ErrorHandlers(GpuX11ErrorHandler, NULL);
}
+#endif
}
-#endif
// Main function for starting the Gpu process.
int GpuMain(const MainFunctionParams& parameters) {
+ base::Time start_time = base::Time::Now();
+
#if defined(USE_LINUX_BREAKPAD)
// Needs to be called after we have chrome::DIR_USER_DATA.
InitCrashReporter();
@@ -66,20 +84,75 @@
#if defined(OS_WIN)
win_util::ScopedCOMInitializer com_initializer;
-#elif defined(GPU_USE_GLX)
- if (!command_line.HasSwitch(switches::kUseGL)) {
- gfx::InitializeGLBindings(gfx::kGLImplementationDesktopGL);
- }
#endif
- GpuProcess gpu_process;
- gpu_process.set_main_thread(new GpuThread());
-
#if defined(USE_X11)
SetGpuX11ErrorHandlers();
#endif
+ // Load the GL implementation and locate the bindings before starting as
+ // this can take a lot of time and the GPU watchdog might terminate the GPU
+ // process.
+ if (!gfx::GLContext::InitializeOneOff())
+ return EXIT_FAILURE;
+
+ GpuProcess gpu_process;
+ GpuThread* gpu_thread = new GpuThread;
+ gpu_process.set_main_thread(gpu_thread);
+
+ // Only enable this experimental feaure for a subset of users.
+ scoped_refptr<base::FieldTrial> watchdog_trial(
+ new base::FieldTrial("GpuWatchdogTrial", 100));
+ int watchdog_timeout = 0;
+ for (int i = kMinGpuTimeout; i <= kMaxGpuTimeout; ++i) {
+ int group = watchdog_trial->AppendGroup(StringPrintf("%dsecs", i),
+ kFieldTrialSize);
+ if (group == watchdog_trial->group()) {
+ watchdog_timeout = i;
+ break;
+ }
+ }
+
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+
+ // 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 =
+ watchdog_timeout != 0 &&
+ !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
+
+// TODO(apatrick): Disable for this commit. I want to enable this feature with
+// a simple single file change that can easily be reverted if need be without
+// losing all the other features of the patch.
+#if 1
+ enable_watchdog = false;
+#endif
+
+ scoped_refptr<GpuWatchdogThread> watchdog_thread;
+ if (enable_watchdog) {
+ watchdog_thread = new GpuWatchdogThread(MessageLoop::current(),
+ watchdog_timeout * 1000);
+ watchdog_thread->Start();
+ }
+
+ // Do this immediately before running the message loop so the correct
+ // initialization time is recorded in the GPU info.
+ gpu_thread->Init(start_time);
+
main_message_loop.Run();
+ if (enable_watchdog)
+ watchdog_thread->Stop();
+
return 0;
}