Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include <math.h> // ceil | |
| 6 | |
| 7 #include "base/string_tokenizer.h" | |
| 5 #include "base/threading/thread_restrictions.h" | 8 #include "base/threading/thread_restrictions.h" |
| 6 #include "build/build_config.h" | 9 #include "build/build_config.h" |
| 7 #include "chrome/browser/metrics/metrics_service.h" | 10 #include "chrome/browser/metrics/metrics_service.h" |
| 8 #include "chrome/browser/metrics/thread_watcher.h" | 11 #include "chrome/browser/metrics/thread_watcher.h" |
| 12 #include "chrome/common/chrome_switches.h" | |
| 9 #include "content/common/notification_service.h" | 13 #include "content/common/notification_service.h" |
| 10 | 14 |
| 11 #if defined(OS_WIN) | 15 #if defined(OS_WIN) |
| 12 #include <Objbase.h> | 16 #include <Objbase.h> |
| 13 #endif | 17 #endif |
| 14 | 18 |
| 15 // static | 19 // static |
| 16 const int ThreadWatcher::kPingCount = 6; | 20 const int ThreadWatcher::kPingCount = 6; |
| 17 | 21 |
| 18 // static | |
| 19 const int ThreadWatcher::kUnresponsiveCount = 6; | |
| 20 | |
| 21 // ThreadWatcher methods and members. | 22 // ThreadWatcher methods and members. |
| 22 ThreadWatcher::ThreadWatcher(const BrowserThread::ID& thread_id, | 23 ThreadWatcher::ThreadWatcher(const BrowserThread::ID& thread_id, |
| 23 const std::string& thread_name, | 24 const std::string& thread_name, |
| 24 const base::TimeDelta& sleep_time, | 25 const base::TimeDelta& sleep_time, |
| 25 const base::TimeDelta& unresponsive_time) | 26 const base::TimeDelta& unresponsive_time, |
| 27 uint32 crash_on_unresponsive_count, | |
| 28 bool crash_on_hang) | |
| 26 : thread_id_(thread_id), | 29 : thread_id_(thread_id), |
| 27 thread_name_(thread_name), | 30 thread_name_(thread_name), |
| 28 sleep_time_(sleep_time), | 31 sleep_time_(sleep_time), |
| 29 unresponsive_time_(unresponsive_time), | 32 unresponsive_time_(unresponsive_time), |
| 30 ping_time_(base::TimeTicks::Now()), | 33 ping_time_(base::TimeTicks::Now()), |
| 31 pong_time_(ping_time_), | 34 pong_time_(ping_time_), |
| 32 ping_sequence_number_(0), | 35 ping_sequence_number_(0), |
| 33 active_(false), | 36 active_(false), |
| 34 ping_count_(kPingCount), | 37 ping_count_(kPingCount), |
| 35 response_time_histogram_(NULL), | 38 response_time_histogram_(NULL), |
| 36 unresponsive_time_histogram_(NULL), | 39 unresponsive_time_histogram_(NULL), |
| 37 unresponsive_count_(0), | 40 unresponsive_count_(0), |
| 38 hung_processing_complete_(false), | 41 hung_processing_complete_(false), |
| 42 crash_on_unresponsive_count_(crash_on_unresponsive_count), | |
| 43 crash_on_hang_(crash_on_hang), | |
| 39 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 44 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
| 40 Initialize(); | 45 Initialize(); |
| 41 } | 46 } |
| 42 | 47 |
| 43 ThreadWatcher::~ThreadWatcher() {} | 48 ThreadWatcher::~ThreadWatcher() {} |
| 44 | 49 |
| 45 // static | 50 // static |
| 46 void ThreadWatcher::StartWatching(const BrowserThread::ID& thread_id, | 51 void ThreadWatcher::StartWatching(const BrowserThread::ID& thread_id, |
| 47 const std::string& thread_name, | 52 const std::string& thread_name, |
| 48 const base::TimeDelta& sleep_time, | 53 const base::TimeDelta& sleep_time, |
| 49 const base::TimeDelta& unresponsive_time) { | 54 const base::TimeDelta& unresponsive_time, |
| 55 uint32 crash_on_unresponsive_count, | |
| 56 bool crash_on_hang) { | |
| 50 DCHECK_GE(sleep_time.InMilliseconds(), 0); | 57 DCHECK_GE(sleep_time.InMilliseconds(), 0); |
| 51 DCHECK_GE(unresponsive_time.InMilliseconds(), sleep_time.InMilliseconds()); | 58 DCHECK_GE(unresponsive_time.InMilliseconds(), sleep_time.InMilliseconds()); |
| 52 | 59 |
| 53 // If we are not on WatchDogThread, then post a task to call StartWatching on | 60 // If we are not on WatchDogThread, then post a task to call StartWatching on |
| 54 // WatchDogThread. | 61 // WatchDogThread. |
| 55 if (!WatchDogThread::CurrentlyOnWatchDogThread()) { | 62 if (!WatchDogThread::CurrentlyOnWatchDogThread()) { |
| 56 WatchDogThread::PostTask( | 63 WatchDogThread::PostTask( |
| 57 FROM_HERE, | 64 FROM_HERE, |
| 58 NewRunnableFunction( | 65 NewRunnableFunction(&ThreadWatcher::StartWatching, |
| 59 &ThreadWatcher::StartWatching, | 66 thread_id, |
| 60 thread_id, thread_name, sleep_time, unresponsive_time)); | 67 thread_name, |
| 68 sleep_time, | |
| 69 unresponsive_time, | |
| 70 crash_on_unresponsive_count, | |
| 71 crash_on_hang)); | |
| 61 return; | 72 return; |
| 62 } | 73 } |
| 63 | 74 |
| 64 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 75 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 65 | 76 |
| 66 // Create a new thread watcher object for the given thread and activate it. | 77 // Create a new thread watcher object for the given thread and activate it. |
| 67 ThreadWatcher* watcher = | 78 ThreadWatcher* watcher = new ThreadWatcher(thread_id, |
| 68 new ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time); | 79 thread_name, |
| 80 sleep_time, | |
| 81 unresponsive_time, | |
| 82 crash_on_unresponsive_count, | |
| 83 crash_on_hang); | |
| 69 DCHECK(watcher); | 84 DCHECK(watcher); |
| 70 // If we couldn't register the thread watcher object, we are shutting down, | 85 // If we couldn't register the thread watcher object, we are shutting down, |
| 71 // then don't activate thread watching. | 86 // then don't activate thread watching. |
| 72 if (!ThreadWatcherList::IsRegistered(thread_id)) | 87 if (!ThreadWatcherList::IsRegistered(thread_id)) |
| 73 return; | 88 return; |
| 74 watcher->ActivateThreadWatching(); | 89 watcher->ActivateThreadWatching(); |
| 75 } | 90 } |
| 76 | 91 |
| 77 void ThreadWatcher::ActivateThreadWatching() { | 92 void ThreadWatcher::ActivateThreadWatching() { |
| 78 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 93 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 | 252 |
| 238 void ThreadWatcher::ResetHangCounters() { | 253 void ThreadWatcher::ResetHangCounters() { |
| 239 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 254 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 240 unresponsive_count_ = 0; | 255 unresponsive_count_ = 0; |
| 241 hung_processing_complete_ = false; | 256 hung_processing_complete_ = false; |
| 242 } | 257 } |
| 243 | 258 |
| 244 void ThreadWatcher::GotNoResponse() { | 259 void ThreadWatcher::GotNoResponse() { |
| 245 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 260 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 246 | 261 |
| 247 // Record how other threads are responding when we don't get a response for | 262 ++unresponsive_count_; |
| 248 // ping message atleast kUnresponsiveCount times. | 263 if (!CrashOnUnresponsiveness()) |
| 249 if (++unresponsive_count_ < kUnresponsiveCount) | |
| 250 return; | 264 return; |
| 251 | 265 |
| 252 // Record total unresponsive_time since last pong message. | 266 // Record total unresponsive_time since last pong message. |
| 253 base::TimeDelta unresponse_time = base::TimeTicks::Now() - pong_time_; | 267 base::TimeDelta unresponse_time = base::TimeTicks::Now() - pong_time_; |
| 254 unresponsive_time_histogram_->AddTime(unresponse_time); | 268 unresponsive_time_histogram_->AddTime(unresponse_time); |
| 255 | 269 |
| 256 // We have already collected stats for the non-responding watched thread. | 270 // We have already collected stats for the non-responding watched thread. |
| 257 if (hung_processing_complete_) | 271 if (hung_processing_complete_) |
| 258 return; | 272 return; |
| 259 | 273 |
| 274 // Record how other threads are responding. | |
| 260 int no_of_responding_threads = 0; | 275 int no_of_responding_threads = 0; |
| 261 int no_of_unresponding_threads = 0; | 276 int no_of_unresponding_threads = 0; |
| 262 ThreadWatcherList::GetStatusOfThreads(&no_of_responding_threads, | 277 ThreadWatcherList::GetStatusOfThreads(&no_of_responding_threads, |
| 263 &no_of_unresponding_threads); | 278 &no_of_unresponding_threads); |
| 264 | 279 |
| 265 // Record how many watched threads are responding. | 280 // Record how many watched threads are responding. |
| 266 responsive_count_histogram_->Add(no_of_responding_threads); | 281 responsive_count_histogram_->Add(no_of_responding_threads); |
| 267 | 282 |
| 268 // Record how many watched threads are not responding. | 283 // Record how many watched threads are not responding. |
| 269 unresponsive_count_histogram_->Add(no_of_unresponding_threads); | 284 unresponsive_count_histogram_->Add(no_of_unresponding_threads); |
| 270 | 285 |
| 271 // Crash the browser if IO thread hasn't responded atleast kUnresponsiveCount | 286 // Crash the browser if the watched thread is to be crashed on hang and if the |
| 272 // times and if the number of other threads is equal to 1. We picked 1 to | 287 // number of other threads responding is equal to 1. We picked 1 to reduce the |
|
jar (doing other things)
2011/06/14 00:56:27
We probably need to parameterize this value "1" as
ramant (doing other things)
2011/06/16 22:26:45
Done.
| |
| 273 // reduce the number of crashes and to get some sample data. | 288 // number of crashes and to get some sample data. |
| 274 if (thread_id_ == BrowserThread::IO && no_of_responding_threads == 1) { | 289 if (crash_on_hang_ && no_of_responding_threads == 1) { |
| 275 int* crash = NULL; | 290 int* crash = NULL; |
| 276 CHECK(crash++); | 291 CHECK(crash+thread_id_); |
| 277 } | 292 } |
| 278 | 293 |
| 279 hung_processing_complete_ = true; | 294 hung_processing_complete_ = true; |
| 280 } | 295 } |
| 281 | 296 |
| 297 bool ThreadWatcher::CrashOnUnresponsiveness() { | |
| 298 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | |
| 299 return unresponsive_count_ >= crash_on_unresponsive_count_; | |
| 300 } | |
| 301 | |
| 282 // ThreadWatcherList methods and members. | 302 // ThreadWatcherList methods and members. |
| 283 // | 303 // |
| 284 // static | 304 // static |
| 285 ThreadWatcherList* ThreadWatcherList::global_ = NULL; | 305 ThreadWatcherList* ThreadWatcherList::global_ = NULL; |
| 286 // static | 306 // static |
| 287 const int ThreadWatcherList::kSleepSeconds = 1; | 307 const int ThreadWatcherList::kSleepSeconds = 1; |
| 288 // static | 308 // static |
| 289 const int ThreadWatcherList::kUnresponsiveSeconds = 2; | 309 const int ThreadWatcherList::kUnresponsiveSeconds = 2; |
| 310 // static | |
| 311 const int ThreadWatcherList::kUnresponsiveCount = 6; | |
| 290 | 312 |
| 291 ThreadWatcherList::ThreadWatcherList() | 313 ThreadWatcherList::ThreadWatcherList(const CommandLine& command_line) |
| 292 : last_wakeup_time_(base::TimeTicks::Now()) { | 314 : last_wakeup_time_(base::TimeTicks::Now()) { |
| 293 // Assert we are not running on WATCHDOG thread. Would be ideal to assert we | 315 // Assert we are not running on WATCHDOG thread. Would be ideal to assert we |
| 294 // are on UI thread, but Unit tests are not running on UI thread. | 316 // are on UI thread, but Unit tests are not running on UI thread. |
| 295 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread()); | 317 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread()); |
|
jar (doing other things)
2011/06/14 00:56:27
Is this is the only reason we have a lock, perhaps
ramant (doing other things)
2011/06/16 22:26:45
Done.
| |
| 296 CHECK(!global_); | 318 CHECK(!global_); |
| 297 global_ = this; | 319 global_ = this; |
| 320 | |
| 298 // Register Notifications observer. | 321 // Register Notifications observer. |
| 299 MetricsService::SetUpNotifications(®istrar_, this); | 322 MetricsService::SetUpNotifications(®istrar_, this); |
| 323 | |
| 324 // Determine the crash_on_unresponsive_count_ based on | |
| 325 // switches::kCrashOnHangSeconds. | |
| 326 crash_on_unresponsive_count_ = kUnresponsiveCount; | |
| 327 | |
| 328 std::string crash_on_hang_seconds = | |
| 329 command_line.GetSwitchValueASCII(switches::kCrashOnHangSeconds); | |
| 330 if (!crash_on_hang_seconds.empty()) { | |
| 331 int crash_seconds = atoi(crash_on_hang_seconds.c_str()); | |
| 332 if (crash_seconds > 0) { | |
| 333 crash_on_unresponsive_count_ = static_cast<int>( | |
| 334 ceil(static_cast<float>(crash_seconds) / kUnresponsiveSeconds)); | |
| 335 } | |
| 336 } | |
| 337 | |
| 338 // Default to crashing the browser if UI or IO threads are not responsive. | |
| 339 std::string crash_on_hang_threads = "UI,IO"; | |
| 340 | |
| 341 // Get the list of unresponsive threads to crash from | |
| 342 // switches::kCrashOnHangThreads. | |
| 343 if (command_line.HasSwitch(switches::kCrashOnHangThreads)) { | |
| 344 crash_on_hang_threads = | |
| 345 command_line.GetSwitchValueASCII(switches::kCrashOnHangThreads); | |
| 346 } | |
| 347 | |
| 348 // Save the thread names in a set. | |
| 349 StringTokenizer t(crash_on_hang_threads, ","); | |
|
jar (doing other things)
2011/06/14 00:56:27
Unless this is really existing practice, it is bet
ramant (doing other things)
2011/06/16 22:26:45
Done.
| |
| 350 while (t.GetNext()) | |
| 351 crash_on_hang_thread_names_.insert(t.token()); | |
| 300 } | 352 } |
| 301 | 353 |
| 302 ThreadWatcherList::~ThreadWatcherList() { | 354 ThreadWatcherList::~ThreadWatcherList() { |
| 303 base::AutoLock auto_lock(lock_); | 355 base::AutoLock auto_lock(lock_); |
| 304 DCHECK(this == global_); | 356 DCHECK(this == global_); |
| 305 global_ = NULL; | 357 global_ = NULL; |
| 306 } | 358 } |
| 307 | 359 |
| 308 // static | 360 // static |
| 309 void ThreadWatcherList::Register(ThreadWatcher* watcher) { | 361 void ThreadWatcherList::Register(ThreadWatcher* watcher) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 326 FROM_HERE, | 378 FROM_HERE, |
| 327 NewRunnableFunction(&ThreadWatcherList::StartWatchingAll), | 379 NewRunnableFunction(&ThreadWatcherList::StartWatchingAll), |
| 328 base::TimeDelta::FromSeconds(120).InMilliseconds()); | 380 base::TimeDelta::FromSeconds(120).InMilliseconds()); |
| 329 return; | 381 return; |
| 330 } | 382 } |
| 331 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 383 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 332 const base::TimeDelta kSleepTime = | 384 const base::TimeDelta kSleepTime = |
| 333 base::TimeDelta::FromSeconds(kSleepSeconds); | 385 base::TimeDelta::FromSeconds(kSleepSeconds); |
| 334 const base::TimeDelta kUnresponsiveTime = | 386 const base::TimeDelta kUnresponsiveTime = |
| 335 base::TimeDelta::FromSeconds(kUnresponsiveSeconds); | 387 base::TimeDelta::FromSeconds(kUnresponsiveSeconds); |
| 336 if (BrowserThread::IsMessageLoopValid(BrowserThread::UI)) { | 388 |
| 337 ThreadWatcher::StartWatching(BrowserThread::UI, "UI", kSleepTime, | 389 StartWatching(BrowserThread::UI, "UI", kSleepTime, kUnresponsiveTime); |
| 338 kUnresponsiveTime); | 390 StartWatching(BrowserThread::IO, "IO", kSleepTime, kUnresponsiveTime); |
| 339 } | 391 StartWatching(BrowserThread::DB, "DB", kSleepTime, kUnresponsiveTime); |
| 340 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { | 392 StartWatching(BrowserThread::FILE, "FILE", kSleepTime, kUnresponsiveTime); |
| 341 ThreadWatcher::StartWatching(BrowserThread::IO, "IO", kSleepTime, | 393 StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime, kUnresponsiveTime); |
| 342 kUnresponsiveTime); | |
| 343 } | |
| 344 if (BrowserThread::IsMessageLoopValid(BrowserThread::DB)) { | |
| 345 ThreadWatcher::StartWatching(BrowserThread::DB, "DB", kSleepTime, | |
| 346 kUnresponsiveTime); | |
| 347 } | |
| 348 if (BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { | |
| 349 ThreadWatcher::StartWatching(BrowserThread::FILE, "FILE", kSleepTime, | |
| 350 kUnresponsiveTime); | |
| 351 } | |
| 352 if (BrowserThread::IsMessageLoopValid(BrowserThread::CACHE)) { | |
| 353 ThreadWatcher::StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime, | |
| 354 kUnresponsiveTime); | |
| 355 } | |
| 356 } | 394 } |
| 357 | 395 |
| 358 // static | 396 // static |
| 359 void ThreadWatcherList::StopWatchingAll() { | 397 void ThreadWatcherList::StopWatchingAll() { |
| 360 // Assert we are not running on WATCHDOG thread. Would be ideal to assert we | 398 // Assert we are not running on WATCHDOG thread. Would be ideal to assert we |
| 361 // are on UI thread, but Unit tests are not running on UI thread. | 399 // are on UI thread, but Unit tests are not running on UI thread. |
| 362 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread()); | 400 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread()); |
| 363 if (!global_) | 401 if (!global_) |
| 364 return; | 402 return; |
| 365 | 403 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 389 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 427 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 390 *no_of_responding_threads = 0; | 428 *no_of_responding_threads = 0; |
| 391 *no_of_unresponding_threads = 0; | 429 *no_of_unresponding_threads = 0; |
| 392 if (!global_) | 430 if (!global_) |
| 393 return; | 431 return; |
| 394 | 432 |
| 395 base::AutoLock auto_lock(global_->lock_); | 433 base::AutoLock auto_lock(global_->lock_); |
| 396 for (RegistrationList::iterator it = global_->registered_.begin(); | 434 for (RegistrationList::iterator it = global_->registered_.begin(); |
| 397 global_->registered_.end() != it; | 435 global_->registered_.end() != it; |
| 398 ++it) { | 436 ++it) { |
| 399 if (it->second->unresponsive_count_ < ThreadWatcher::kUnresponsiveCount) | 437 if (it->second->CrashOnUnresponsiveness()) |
| 438 ++(*no_of_unresponding_threads); | |
| 439 else | |
| 400 ++(*no_of_responding_threads); | 440 ++(*no_of_responding_threads); |
| 401 else | |
| 402 ++(*no_of_unresponding_threads); | |
| 403 } | 441 } |
| 404 } | 442 } |
| 405 | 443 |
| 444 // static | |
| 445 void ThreadWatcherList::StartWatching( | |
| 446 const BrowserThread::ID& thread_id, | |
| 447 const std::string& thread_name, | |
| 448 const base::TimeDelta& sleep_time, | |
| 449 const base::TimeDelta& unresponsive_time) { | |
| 450 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | |
| 451 | |
| 452 if (!BrowserThread::IsMessageLoopValid(thread_id)) | |
| 453 return; | |
| 454 | |
| 455 bool crash_on_hang; | |
| 456 uint32 crash_on_unresponsive_count; | |
| 457 { | |
| 458 if (!global_) | |
| 459 return; | |
| 460 base::AutoLock auto_lock(global_->lock_); | |
| 461 | |
| 462 // Hold the lock on global_ so that it is not deleted. | |
| 463 crash_on_hang = global_->PreLockedCrashOnHang(thread_name); | |
| 464 crash_on_unresponsive_count = global_->PreLockedCrashOnUnresponsiveCount(); | |
| 465 } | |
| 466 | |
| 467 ThreadWatcher::StartWatching(thread_id, | |
| 468 thread_name, | |
| 469 sleep_time, | |
| 470 unresponsive_time, | |
| 471 crash_on_unresponsive_count, | |
| 472 crash_on_hang); | |
| 473 } | |
| 474 | |
| 475 uint32 ThreadWatcherList::CrashOnUnresponsiveCount() { | |
| 476 base::AutoLock auto_lock(lock_); | |
| 477 return PreLockedCrashOnUnresponsiveCount(); | |
| 478 } | |
| 479 | |
| 480 bool ThreadWatcherList::CrashOnHang(const std::string& thread_name) { | |
| 481 base::AutoLock auto_lock(lock_); | |
| 482 return PreLockedCrashOnHang(thread_name); | |
| 483 } | |
| 484 | |
| 485 bool ThreadWatcherList::PreLockedCrashOnHang( | |
| 486 const std::string& thread_name) const { | |
| 487 std::set<std::string>::const_iterator it = | |
| 488 crash_on_hang_thread_names_.find(thread_name); | |
| 489 return (it != crash_on_hang_thread_names_.end()); | |
| 490 } | |
| 491 | |
| 406 void ThreadWatcherList::DeleteAll() { | 492 void ThreadWatcherList::DeleteAll() { |
| 407 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 493 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 408 base::AutoLock auto_lock(lock_); | 494 base::AutoLock auto_lock(lock_); |
| 409 while (!registered_.empty()) { | 495 while (!registered_.empty()) { |
| 410 RegistrationList::iterator it = registered_.begin(); | 496 RegistrationList::iterator it = registered_.begin(); |
| 411 delete it->second; | 497 delete it->second; |
| 412 registered_.erase(it->first); | 498 registered_.erase(it->first); |
| 413 } | 499 } |
| 414 } | 500 } |
| 415 | 501 |
| 416 void ThreadWatcherList::Observe(NotificationType type, | 502 void ThreadWatcherList::Observe(NotificationType type, |
| 417 const NotificationSource& source, | 503 const NotificationSource& source, |
| 418 const NotificationDetails& details) { | 504 const NotificationDetails& details) { |
| 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 420 // There is some user activity, see if thread watchers are to be awakened. | 506 // There is some user activity, see if thread watchers are to be awakened. |
| 421 bool need_to_awaken = false; | 507 bool need_to_awaken = false; |
| 422 base::TimeTicks now = base::TimeTicks::Now(); | 508 base::TimeTicks now = base::TimeTicks::Now(); |
| 423 { | 509 { |
| 424 base::AutoLock lock(lock_); | 510 base::AutoLock auto_lock(lock_); |
| 425 if (now - last_wakeup_time_ > base::TimeDelta::FromSeconds(kSleepSeconds)) { | 511 if (now - last_wakeup_time_ > base::TimeDelta::FromSeconds(kSleepSeconds)) { |
| 426 need_to_awaken = true; | 512 need_to_awaken = true; |
| 427 last_wakeup_time_ = now; | 513 last_wakeup_time_ = now; |
| 428 } | 514 } |
| 429 } | 515 } |
| 430 if (need_to_awaken) { | 516 if (need_to_awaken) { |
| 431 WatchDogThread::PostTask( | 517 WatchDogThread::PostTask( |
| 432 FROM_HERE, | 518 FROM_HERE, |
| 433 NewRunnableMethod(this, &ThreadWatcherList::WakeUpAll)); | 519 NewRunnableMethod(this, &ThreadWatcherList::WakeUpAll)); |
| 434 } | 520 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 watchdog_thread_ = NULL; | 627 watchdog_thread_ = NULL; |
| 542 } | 628 } |
| 543 | 629 |
| 544 void WatchDogThread::CleanUpAfterMessageLoopDestruction() { | 630 void WatchDogThread::CleanUpAfterMessageLoopDestruction() { |
| 545 #if defined(OS_WIN) | 631 #if defined(OS_WIN) |
| 546 // Closes the COM library on the current thread. CoInitialize must | 632 // Closes the COM library on the current thread. CoInitialize must |
| 547 // be balanced by a corresponding call to CoUninitialize. | 633 // be balanced by a corresponding call to CoUninitialize. |
| 548 CoUninitialize(); | 634 CoUninitialize(); |
| 549 #endif | 635 #endif |
| 550 } | 636 } |
| OLD | NEW |