| Index: content/gpu/gpu_watchdog_thread.cc
|
| diff --git a/content/gpu/gpu_watchdog_thread.cc b/content/gpu/gpu_watchdog_thread.cc
|
| index 02b6bff8040e8f6c7c464f309c31761da0f508f9..6a6f45924a015846847131306e9ddda9ddff6eb3 100644
|
| --- a/content/gpu/gpu_watchdog_thread.cc
|
| +++ b/content/gpu/gpu_watchdog_thread.cc
|
| @@ -26,6 +26,9 @@ const int64 kCheckPeriodMs = 2000;
|
| const base::FilePath::CharType
|
| kTtyFilePath[] = FILE_PATH_LITERAL("/sys/class/tty/tty0/active");
|
| #endif
|
| +#if defined(USE_X11)
|
| +const unsigned char text[20] = "check";
|
| +#endif
|
| } // namespace
|
|
|
| GpuWatchdogThread::GpuWatchdogThread(int timeout)
|
| @@ -39,6 +42,11 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
|
| #endif
|
| task_observer_(this),
|
| suspended_(false),
|
| +#if defined(USE_X11)
|
| + display_(NULL),
|
| + window_(0),
|
| + atom_(None),
|
| +#endif
|
| weak_factory_(this) {
|
| DCHECK(timeout >= 0);
|
|
|
| @@ -59,6 +67,9 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
|
| #if defined(OS_CHROMEOS)
|
| tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
|
| #endif
|
| +#if defined(USE_X11)
|
| + SetupXServer();
|
| +#endif
|
| watched_message_loop_->AddTaskObserver(&task_observer_);
|
| }
|
|
|
| @@ -123,6 +134,11 @@ GpuWatchdogThread::~GpuWatchdogThread() {
|
| fclose(tty_file_);
|
| #endif
|
|
|
| +#if defined(USE_X11)
|
| + XDestroyWindow(display_, window_);
|
| + XCloseDisplay(display_);
|
| +#endif
|
| +
|
| watched_message_loop_->RemoveTaskObserver(&task_observer_);
|
| }
|
|
|
| @@ -188,9 +204,8 @@ void GpuWatchdogThread::OnCheck(bool after_suspend) {
|
| // not respond in time.
|
| message_loop()->PostDelayedTask(
|
| FROM_HERE,
|
| - base::Bind(
|
| - &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
|
| - weak_factory_.GetWeakPtr()),
|
| + base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
|
| + weak_factory_.GetWeakPtr()),
|
| timeout);
|
| }
|
|
|
| @@ -224,6 +239,52 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
|
| return;
|
| }
|
|
|
| +#if defined(USE_X11)
|
| + XWindowAttributes attributes;
|
| + XGetWindowAttributes(display_, window_, &attributes);
|
| +
|
| + XSelectInput(display_, window_, PropertyChangeMask);
|
| + SetupXChangeProp();
|
| +
|
| + XFlush(display_);
|
| +
|
| + // We wait for the property change event with a timeout. If it arrives we know
|
| + // that X is responsive and is not the cause of the watchdog trigger, so we
|
| + // should
|
| + // terminate. If it times out, it may be due to X taking a long time, but
|
| + // terminating won't help, so ignore the watchdog trigger.
|
| + XEvent event_return;
|
| + base::TimeTicks deadline = base::TimeTicks::Now() + timeout_;
|
| + while (true) {
|
| + base::TimeDelta delta = deadline - base::TimeTicks::Now();
|
| + if (delta < base::TimeDelta()) {
|
| + return;
|
| + } else {
|
| + while (XCheckWindowEvent(display_, window_, PropertyChangeMask,
|
| + &event_return)) {
|
| + if (MatchXEventAtom(&event_return))
|
| + break;
|
| + }
|
| + struct pollfd fds[1];
|
| + fds[0].fd = XConnectionNumber(display_);
|
| + fds[0].events = POLLIN;
|
| + int status = poll(fds, 1, delta.InMilliseconds());
|
| + if (status == -1) {
|
| + if (errno == EINTR) {
|
| + continue;
|
| + } else {
|
| + LOG(FATAL) << "Lost X connection, aborting.";
|
| + break;
|
| + }
|
| + } else if (status == 0) {
|
| + return;
|
| + } else {
|
| + continue;
|
| + }
|
| + }
|
| + }
|
| +#endif
|
| +
|
| // For minimal developer annoyance, don't keep terminating. You need to skip
|
| // the call to base::Process::Terminate below in a debugger for this to be
|
| // useful.
|
| @@ -259,6 +320,28 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
|
| terminated = true;
|
| }
|
|
|
| +#if defined(USE_X11)
|
| +void GpuWatchdogThread::SetupXServer() {
|
| + display_ = XOpenDisplay(NULL);
|
| + window_ = XCreateWindow(display_, DefaultRootWindow(display_), 0, 0, 1, 1, 0,
|
| + CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
|
| + atom_ = XInternAtom(display_, "CHECK", False);
|
| +}
|
| +
|
| +void GpuWatchdogThread::SetupXChangeProp() {
|
| + XChangeProperty(display_, window_, atom_, XA_STRING, 8, PropModeReplace, text,
|
| + (arraysize(text) - 1));
|
| +}
|
| +
|
| +bool GpuWatchdogThread::MatchXEventAtom(XEvent* event) {
|
| + if (event->xproperty.window == window_ && event->type == PropertyNotify &&
|
| + event->xproperty.atom == atom_)
|
| + return true;
|
| +
|
| + return false;
|
| +}
|
| +
|
| +#endif
|
| void GpuWatchdogThread::AddPowerObserver() {
|
| message_loop()->PostTask(
|
| FROM_HERE,
|
|
|