Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: content/gpu/gpu_watchdog_thread.cc

Issue 836473003: Avoid gpu watchdog crash on timeout if X is un-responsive. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review comments updated. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/gpu/gpu_watchdog_thread.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if defined(OS_WIN) 5 #if defined(OS_WIN)
6 #include <windows.h> 6 #include <windows.h>
7 #endif 7 #endif
8 8
9 #include "content/gpu/gpu_watchdog_thread.h" 9 #include "content/gpu/gpu_watchdog_thread.h"
10 10
(...skipping 21 matching lines...) Expand all
32 : base::Thread("Watchdog"), 32 : base::Thread("Watchdog"),
33 watched_message_loop_(base::MessageLoop::current()), 33 watched_message_loop_(base::MessageLoop::current()),
34 timeout_(base::TimeDelta::FromMilliseconds(timeout)), 34 timeout_(base::TimeDelta::FromMilliseconds(timeout)),
35 armed_(false), 35 armed_(false),
36 #if defined(OS_WIN) 36 #if defined(OS_WIN)
37 watched_thread_handle_(0), 37 watched_thread_handle_(0),
38 arm_cpu_time_(), 38 arm_cpu_time_(),
39 #endif 39 #endif
40 task_observer_(this), 40 task_observer_(this),
41 suspended_(false), 41 suspended_(false),
42 #if defined(USE_X11)
43 display_(NULL),
44 window_(0),
45 atom_(None),
46 #endif
42 weak_factory_(this) { 47 weak_factory_(this) {
43 DCHECK(timeout >= 0); 48 DCHECK(timeout >= 0);
44 49
45 #if defined(OS_WIN) 50 #if defined(OS_WIN)
46 // GetCurrentThread returns a pseudo-handle that cannot be used by one thread 51 // GetCurrentThread returns a pseudo-handle that cannot be used by one thread
47 // to identify another. DuplicateHandle creates a "real" handle that can be 52 // to identify another. DuplicateHandle creates a "real" handle that can be
48 // used for this purpose. 53 // used for this purpose.
49 BOOL result = DuplicateHandle(GetCurrentProcess(), 54 BOOL result = DuplicateHandle(GetCurrentProcess(),
50 GetCurrentThread(), 55 GetCurrentThread(),
51 GetCurrentProcess(), 56 GetCurrentProcess(),
52 &watched_thread_handle_, 57 &watched_thread_handle_,
53 THREAD_QUERY_INFORMATION, 58 THREAD_QUERY_INFORMATION,
54 FALSE, 59 FALSE,
55 0); 60 0);
56 DCHECK(result); 61 DCHECK(result);
57 #endif 62 #endif
58 63
59 #if defined(OS_CHROMEOS) 64 #if defined(OS_CHROMEOS)
60 tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r"); 65 tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
61 #endif 66 #endif
67 #if defined(USE_X11)
68 SetupXServer();
69 #endif
62 watched_message_loop_->AddTaskObserver(&task_observer_); 70 watched_message_loop_->AddTaskObserver(&task_observer_);
63 } 71 }
64 72
65 void GpuWatchdogThread::PostAcknowledge() { 73 void GpuWatchdogThread::PostAcknowledge() {
66 // Called on the monitored thread. Responds with OnAcknowledge. Cannot use 74 // Called on the monitored thread. Responds with OnAcknowledge. Cannot use
67 // the method factory. Rely on reference counting instead. 75 // the method factory. Rely on reference counting instead.
68 message_loop()->PostTask( 76 message_loop()->PostTask(
69 FROM_HERE, 77 FROM_HERE,
70 base::Bind(&GpuWatchdogThread::OnAcknowledge, this)); 78 base::Bind(&GpuWatchdogThread::OnAcknowledge, this));
71 } 79 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 124
117 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); 125 base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
118 if (power_monitor) 126 if (power_monitor)
119 power_monitor->RemoveObserver(this); 127 power_monitor->RemoveObserver(this);
120 128
121 #if defined(OS_CHROMEOS) 129 #if defined(OS_CHROMEOS)
122 if (tty_file_) 130 if (tty_file_)
123 fclose(tty_file_); 131 fclose(tty_file_);
124 #endif 132 #endif
125 133
134 #if defined(USE_X11)
135 XDestroyWindow(display_, window_);
136 XCloseDisplay(display_);
137 #endif
138
126 watched_message_loop_->RemoveTaskObserver(&task_observer_); 139 watched_message_loop_->RemoveTaskObserver(&task_observer_);
127 } 140 }
128 141
129 void GpuWatchdogThread::OnAcknowledge() { 142 void GpuWatchdogThread::OnAcknowledge() {
130 CHECK(base::PlatformThread::CurrentId() == thread_id()); 143 CHECK(base::PlatformThread::CurrentId() == thread_id());
131 144
132 // The check has already been acknowledged and another has already been 145 // The check has already been acknowledged and another has already been
133 // scheduled by a previous call to OnAcknowledge. It is normal for a 146 // scheduled by a previous call to OnAcknowledge. It is normal for a
134 // watched thread to see armed_ being true multiple times before 147 // watched thread to see armed_ being true multiple times before
135 // the OnAcknowledge task is run on the watchdog thread. 148 // the OnAcknowledge task is run on the watchdog thread.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 // TaskObserver. Any other tasks that are pending on the watched thread will 194 // TaskObserver. Any other tasks that are pending on the watched thread will
182 // also wake up the observer. This simply ensures there is at least one. 195 // also wake up the observer. This simply ensures there is at least one.
183 watched_message_loop_->PostTask( 196 watched_message_loop_->PostTask(
184 FROM_HERE, 197 FROM_HERE,
185 base::Bind(&base::DoNothing)); 198 base::Bind(&base::DoNothing));
186 199
187 // Post a task to the watchdog thread to exit if the monitored thread does 200 // Post a task to the watchdog thread to exit if the monitored thread does
188 // not respond in time. 201 // not respond in time.
189 message_loop()->PostDelayedTask( 202 message_loop()->PostDelayedTask(
190 FROM_HERE, 203 FROM_HERE,
191 base::Bind( 204 base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
192 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, 205 weak_factory_.GetWeakPtr()),
193 weak_factory_.GetWeakPtr()),
194 timeout); 206 timeout);
195 } 207 }
196 208
197 // Use the --disable-gpu-watchdog command line switch to disable this. 209 // Use the --disable-gpu-watchdog command line switch to disable this.
198 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { 210 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
199 // Should not get here while the system is suspended. 211 // Should not get here while the system is suspended.
200 DCHECK(!suspended_); 212 DCHECK(!suspended_);
201 213
202 #if defined(OS_WIN) 214 #if defined(OS_WIN)
203 // Defer termination until a certain amount of CPU time has elapsed on the 215 // Defer termination until a certain amount of CPU time has elapsed on the
(...skipping 13 matching lines...) Expand all
217 // If the watchdog woke up significantly behind schedule, disarm and reset 229 // If the watchdog woke up significantly behind schedule, disarm and reset
218 // the watchdog check. This is to prevent the watchdog thread from terminating 230 // the watchdog check. This is to prevent the watchdog thread from terminating
219 // when a machine wakes up from sleep or hibernation, which would otherwise 231 // when a machine wakes up from sleep or hibernation, which would otherwise
220 // appear to be a hang. 232 // appear to be a hang.
221 if (base::Time::Now() > suspension_timeout_) { 233 if (base::Time::Now() > suspension_timeout_) {
222 armed_ = false; 234 armed_ = false;
223 OnCheck(true); 235 OnCheck(true);
224 return; 236 return;
225 } 237 }
226 238
239 #if defined(USE_X11)
240 XWindowAttributes attributes;
241 XGetWindowAttributes(display_, window_, &attributes);
242
243 XSelectInput(display_, window_, PropertyChangeMask);
244 SetupXChangeProp();
245
246 XFlush(display_);
247
248 XEvent event_return;
249 while (1) {
250 struct pollfd fds[1];
251 fds[0].fd = XConnectionNumber(display_);
252 fds[0].events = POLLIN;
253 int status = poll(fds, 1, timeout_.InMilliseconds());
piman 2015/02/06 22:49:53 1- we need to handle error values. In particular E
sohanjg 2015/02/13 05:18:00 Done.
254 if (status == 0) {
255 break;
256 }
257 if (XCheckWindowEvent(display_, window_, PropertyChangeMask,
258 &event_return)) {
259 return;
piman 2015/02/06 22:49:54 So, if I follow the overall logic, you're testing
sohanjg 2015/02/13 05:18:00 Acknowledged.
260 }
261 }
262 #endif
263
227 // For minimal developer annoyance, don't keep terminating. You need to skip 264 // For minimal developer annoyance, don't keep terminating. You need to skip
228 // the call to base::Process::Terminate below in a debugger for this to be 265 // the call to base::Process::Terminate below in a debugger for this to be
229 // useful. 266 // useful.
230 static bool terminated = false; 267 static bool terminated = false;
231 if (terminated) 268 if (terminated)
232 return; 269 return;
233 270
234 #if defined(OS_WIN) 271 #if defined(OS_WIN)
235 if (IsDebuggerPresent()) 272 if (IsDebuggerPresent())
236 return; 273 return;
(...skipping 15 matching lines...) Expand all
252 289
253 LOG(ERROR) << "The GPU process hung. Terminating after " 290 LOG(ERROR) << "The GPU process hung. Terminating after "
254 << timeout_.InMilliseconds() << " ms."; 291 << timeout_.InMilliseconds() << " ms.";
255 292
256 // Deliberately crash the process to create a crash dump. 293 // Deliberately crash the process to create a crash dump.
257 *((volatile int*)0) = 0x1337; 294 *((volatile int*)0) = 0x1337;
258 295
259 terminated = true; 296 terminated = true;
260 } 297 }
261 298
299 #if defined(USE_X11)
300 void GpuWatchdogThread::SetupXServer() {
301 display_ = XOpenDisplay(NULL);
302 window_ = XCreateWindow(display_, DefaultRootWindow(display_), 0, 0, 1, 1, 0,
303 CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
304 }
305
306 void GpuWatchdogThread::SetupXChangeProp() {
307 unsigned char text[20] = "check";
piman 2015/02/06 22:49:53 const unsigned char text[] = "check";
sohanjg 2015/02/13 05:18:00 Done.
308 atom_ = XInternAtom(display_, "CHK", False);
piman 2015/02/06 22:49:54 We shouldn't need to do this every time. Do you wa
sohanjg 2015/02/13 05:18:00 Done.
309 XChangeProperty(display_, window_, atom_, XA_STRING, 8, PropModeReplace, text,
310 5);
piman 2015/02/06 22:49:53 strlen(text) instead of 5? Do we need to change th
sohanjg 2015/02/13 05:18:00 We are getting the event even if we dont change.
311 }
312 #endif
262 void GpuWatchdogThread::AddPowerObserver() { 313 void GpuWatchdogThread::AddPowerObserver() {
263 message_loop()->PostTask( 314 message_loop()->PostTask(
264 FROM_HERE, 315 FROM_HERE,
265 base::Bind(&GpuWatchdogThread::OnAddPowerObserver, this)); 316 base::Bind(&GpuWatchdogThread::OnAddPowerObserver, this));
266 } 317 }
267 318
268 void GpuWatchdogThread::OnAddPowerObserver() { 319 void GpuWatchdogThread::OnAddPowerObserver() {
269 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); 320 base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
270 DCHECK(power_monitor); 321 DCHECK(power_monitor);
271 power_monitor->AddObserver(this); 322 power_monitor->AddObserver(this);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 // not increasing. The other is where either the kernel hangs and never 365 // not increasing. The other is where either the kernel hangs and never
315 // returns to user level or where user level code 366 // returns to user level or where user level code
316 // calls into kernel level repeatedly, giving up its quanta before it is 367 // calls into kernel level repeatedly, giving up its quanta before it is
317 // tracked, for example a loop that repeatedly Sleeps. 368 // tracked, for example a loop that repeatedly Sleeps.
318 return base::TimeDelta::FromMilliseconds(static_cast<int64>( 369 return base::TimeDelta::FromMilliseconds(static_cast<int64>(
319 (user_time64.QuadPart + kernel_time64.QuadPart) / 10000)); 370 (user_time64.QuadPart + kernel_time64.QuadPart) / 10000));
320 } 371 }
321 #endif 372 #endif
322 373
323 } // namespace content 374 } // namespace content
OLDNEW
« no previous file with comments | « content/gpu/gpu_watchdog_thread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698