diff options
author | sohan.jyoti <sohan.jyoti@samsung.com> | 2015-02-17 19:13:42 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-18 03:14:33 +0000 |
commit | cf28abf824523e4d78b683680fdf87de4dc66901 (patch) | |
tree | 2a51690d855363075add88bfc855341e8ddcbaf1 /content/gpu | |
parent | 72b4f2deb9eaf9c0048ef92a0f4c18011b4b6c24 (diff) | |
download | chromium_src-cf28abf824523e4d78b683680fdf87de4dc66901.zip chromium_src-cf28abf824523e4d78b683680fdf87de4dc66901.tar.gz chromium_src-cf28abf824523e4d78b683680fdf87de4dc66901.tar.bz2 |
On timeout, we wait for a XProperty change event with additional
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.
BUG=432095
Review URL: https://codereview.chromium.org/836473003
Cr-Commit-Position: refs/heads/master@{#316757}
Diffstat (limited to 'content/gpu')
-rw-r--r-- | content/gpu/gpu_watchdog_thread.cc | 89 | ||||
-rw-r--r-- | content/gpu/gpu_watchdog_thread.h | 23 |
2 files changed, 109 insertions, 3 deletions
diff --git a/content/gpu/gpu_watchdog_thread.cc b/content/gpu/gpu_watchdog_thread.cc index 02b6bff..6a6f459 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, diff --git a/content/gpu/gpu_watchdog_thread.h b/content/gpu/gpu_watchdog_thread.h index c766ca3..9dd184a 100644 --- a/content/gpu/gpu_watchdog_thread.h +++ b/content/gpu/gpu_watchdog_thread.h @@ -12,6 +12,18 @@ #include "base/threading/thread.h" #include "base/time/time.h" #include "content/common/gpu/gpu_watchdog.h" +#include "ui/gfx/native_widget_types.h" + +#if defined(USE_X11) +extern "C" { +#include <X11/Xlib.h> +#include <X11/Xatom.h> +} +#include <sys/poll.h> +#include "ui/base/x/x11_util.h" +#include "ui/gfx/x/x11_types.h" + +#endif namespace content { @@ -62,6 +74,11 @@ class GpuWatchdogThread : public base::Thread, void OnAcknowledge(); void OnCheck(bool after_suspend); void DeliberatelyTerminateToRecoverFromHang(); +#if defined(USE_X11) + void SetupXServer(); + void SetupXChangeProp(); + bool MatchXEventAtom(XEvent* event); +#endif void OnAddPowerObserver(); @@ -93,6 +110,12 @@ class GpuWatchdogThread : public base::Thread, FILE* tty_file_; #endif +#if defined(USE_X11) + XDisplay* display_; + gfx::AcceleratedWidget window_; + XAtom atom_; +#endif + base::WeakPtrFactory<GpuWatchdogThread> weak_factory_; DISALLOW_COPY_AND_ASSIGN(GpuWatchdogThread); |