1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_THREADING_HANG_WATCHER_H_ 6 #define BASE_THREADING_HANG_WATCHER_H_ 7 8 #include <atomic> 9 #include <cstdint> 10 #include <memory> 11 #include <type_traits> 12 #include <vector> 13 14 #include "base/atomicops.h" 15 #include "base/auto_reset.h" 16 #include "base/base_export.h" 17 #include "base/bits.h" 18 #include "base/compiler_specific.h" 19 #include "base/dcheck_is_on.h" 20 #include "base/debug/crash_logging.h" 21 #include "base/functional/callback.h" 22 #include "base/functional/callback_forward.h" 23 #include "base/functional/callback_helpers.h" 24 #include "base/gtest_prod_util.h" 25 #include "base/memory/memory_pressure_listener.h" 26 #include "base/memory/raw_ptr.h" 27 #include "base/memory/raw_ptr_exclusion.h" 28 #include "base/synchronization/lock.h" 29 #include "base/synchronization/waitable_event.h" 30 #include "base/template_util.h" 31 #include "base/thread_annotations.h" 32 #include "base/threading/platform_thread.h" 33 #include "base/threading/simple_thread.h" 34 #include "base/threading/thread_checker.h" 35 #include "base/time/tick_clock.h" 36 #include "base/time/time.h" 37 #include "build/build_config.h" 38 39 namespace base { 40 class WatchHangsInScope; 41 namespace internal { 42 class HangWatchState; 43 } // namespace internal 44 } // namespace base 45 46 namespace base { 47 48 // Instantiate a WatchHangsInScope in a code scope to register to be 49 // watched for hangs of more than |timeout| by the HangWatcher. 50 // 51 // Example usage: 52 // 53 // void FooBar(){ 54 // WatchHangsInScope scope(base::Seconds(5)); 55 // DoWork(); 56 // } 57 // 58 // If DoWork() takes more than 5s to run and the HangWatcher 59 // inspects the thread state before Foobar returns a hang will be 60 // reported. 61 // 62 // WatchHangsInScopes are typically meant to live on the stack. In some 63 // cases it's necessary to keep a WatchHangsInScope instance as a class 64 // member but special care is required when doing so as a WatchHangsInScope 65 // that stays alive longer than intended will generate non-actionable hang 66 // reports. 67 class BASE_EXPORT [[maybe_unused, nodiscard]] WatchHangsInScope { 68 public: 69 // A good default value needs to be large enough to represent a significant 70 // hang and avoid noise while being small enough to not exclude too many 71 // hangs. The nature of the work that gets executed on the thread is also 72 // important. We can be much stricter when monitoring a UI thread compared to 73 // a ThreadPool thread for example. 74 static constexpr base::TimeDelta kDefaultHangWatchTime = base::Seconds(10); 75 76 // Constructing/destructing thread must be the same thread. 77 explicit WatchHangsInScope(TimeDelta timeout = kDefaultHangWatchTime); 78 ~WatchHangsInScope(); 79 80 WatchHangsInScope(const WatchHangsInScope&) = delete; 81 WatchHangsInScope& operator=(const WatchHangsInScope&) = delete; 82 83 private: 84 // Will be true if the object actually set a deadline and false if not. 85 bool took_effect_ = true; 86 87 // This object should always be constructed and destructed on the same thread. 88 THREAD_CHECKER(thread_checker_); 89 90 // The deadline set by the previous WatchHangsInScope created on this 91 // thread. Stored so it can be restored when this WatchHangsInScope is 92 // destroyed. 93 TimeTicks previous_deadline_; 94 95 // Indicates whether the kIgnoreCurrentWatchHangsInScope flag must be set upon 96 // exiting this WatchHangsInScope if a call to InvalidateActiveExpectations() 97 // previously suspended hang watching. 98 bool set_hangs_ignored_on_exit_ = false; 99 100 #if DCHECK_IS_ON() 101 // The previous WatchHangsInScope created on this thread. 102 // This field is not a raw_ptr<> because it was filtered by the rewriter for: 103 // #union 104 RAW_PTR_EXCLUSION WatchHangsInScope* previous_watch_hangs_in_scope_; 105 #endif 106 }; 107 108 // Monitors registered threads for hangs by inspecting their associated 109 // HangWatchStates for deadline overruns. This happens at a regular interval on 110 // a separate thread. Only one instance of HangWatcher can exist at a time 111 // within a single process. This instance must outlive all monitored threads. 112 class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { 113 public: 114 // Describes the type of a process for logging purposes. 115 enum class ProcessType { 116 kUnknownProcess = 0, 117 kBrowserProcess = 1, 118 kGPUProcess = 2, 119 kRendererProcess = 3, 120 kUtilityProcess = 4, 121 kMax = kUtilityProcess 122 }; 123 124 // Describes the type of a thread for logging purposes. 125 enum class ThreadType { 126 kIOThread = 0, 127 kMainThread = 1, 128 kThreadPoolThread = 2, 129 kMax = kThreadPoolThread 130 }; 131 132 // Notes on lifetime: 133 // 1) The first invocation of the constructor will set the global instance 134 // accessible through GetInstance(). 135 // 2) In production HangWatcher is always purposefuly leaked. 136 // 3) If not leaked HangWatcher is always constructed and destructed from 137 // the same thread. 138 // 4) There can never be more than one instance of HangWatcher at a time. 139 // The class is not base::Singleton derived because it needs to destroyed 140 // in tests. 141 HangWatcher(); 142 143 // Clears the global instance for the class. 144 ~HangWatcher() override; 145 146 HangWatcher(const HangWatcher&) = delete; 147 HangWatcher& operator=(const HangWatcher&) = delete; 148 149 static void CreateHangWatcherInstance(); 150 151 // Returns a non-owning pointer to the global HangWatcher instance. 152 static HangWatcher* GetInstance(); 153 154 // Initializes HangWatcher. Must be called once on the main thread during 155 // startup while single-threaded. 156 static void InitializeOnMainThread(ProcessType process_type); 157 158 // Returns the values that were set through InitializeOnMainThread() to their 159 // default value. Used for testing since in prod initialization should happen 160 // only once. 161 static void UnitializeOnMainThreadForTesting(); 162 163 // Thread safe functions to verify if hang watching is activated. If called 164 // before InitializeOnMainThread returns the default value which is false. 165 static bool IsEnabled(); 166 static bool IsThreadPoolHangWatchingEnabled(); 167 static bool IsIOThreadHangWatchingEnabled(); 168 169 // Returns true if crash dump reporting is configured for any thread type. 170 static bool IsCrashReportingEnabled(); 171 172 // Use to avoid capturing hangs for operations known to take unbounded time 173 // like waiting for user input. WatchHangsInScope objects created after this 174 // call will take effect. To resume watching for hangs create a new 175 // WatchHangsInScope after the unbounded operation finishes. 176 // 177 // Example usage: 178 // { 179 // WatchHangsInScope scope_1; 180 // { 181 // WatchHangsInScope scope_2; 182 // InvalidateActiveExpectations(); 183 // WaitForUserInput(); 184 // } 185 // 186 // WatchHangsInScope scope_4; 187 // } 188 // 189 // WatchHangsInScope scope_5; 190 // 191 // In this example hang watching is disabled for WatchHangsInScopes 1 and 2 192 // since they were both active at the time of the invalidation. 193 // WatchHangsInScopes 4 and 5 are unaffected since they were created after the 194 // end of the WatchHangsInScope that was current at the time of invalidation. 195 // 196 static void InvalidateActiveExpectations(); 197 198 // Sets up the calling thread to be monitored for threads. Returns a 199 // ScopedClosureRunner that unregisters the thread. This closure has to be 200 // called from the registered thread before it's joined. Returns a null 201 // closure in the case where there is no HangWatcher instance to register the 202 // thread with. 203 [[nodiscard]] static ScopedClosureRunner RegisterThread( 204 ThreadType thread_type); 205 206 // Choose a closure to be run at the end of each call to Monitor(). Use only 207 // for testing. Reentering the HangWatcher in the closure must be done with 208 // care. It should only be done through certain testing functions because 209 // deadlocks are possible. 210 void SetAfterMonitorClosureForTesting(base::RepeatingClosure closure); 211 212 // Choose a closure to be run instead of recording the hang. Used to test 213 // that certain conditions hold true at the time of recording. Use only 214 // for testing. Reentering the HangWatcher in the closure must be done with 215 // care. It should only be done through certain testing functions because 216 // deadlocks are possible. 217 void SetOnHangClosureForTesting(base::RepeatingClosure closure); 218 219 // Set a monitoring period other than the default. Use only for 220 // testing. 221 void SetMonitoringPeriodForTesting(base::TimeDelta period); 222 223 // Choose a callback to invoke right after waiting to monitor in Wait(). Use 224 // only for testing. 225 void SetAfterWaitCallbackForTesting( 226 RepeatingCallback<void(TimeTicks)> callback); 227 228 // Force the monitoring loop to resume and evaluate whether to continue. 229 // This can trigger a call to Monitor() or not depending on why the 230 // HangWatcher thread is sleeping. Use only for testing. 231 void SignalMonitorEventForTesting(); 232 233 // Call to make sure no more monitoring takes place. The 234 // function is thread-safe and can be called at anytime but won't stop 235 // monitoring that is currently taking place. Use only for testing. 236 static void StopMonitoringForTesting(); 237 238 // Replace the clock used when calculating time spent 239 // sleeping. Use only for testing. 240 void SetTickClockForTesting(const base::TickClock* tick_clock); 241 242 // Use to block until the hang is recorded. Allows the caller to halt 243 // execution so it does not overshoot the hang watch target and result in a 244 // non-actionable stack trace in the crash recorded. 245 void BlockIfCaptureInProgress(); 246 247 // Begin executing the monitoring loop on the HangWatcher thread. 248 void Start(); 249 250 // Returns the value of the crash key with the time since last system power 251 // resume. 252 std::string GetTimeSinceLastSystemPowerResumeCrashKeyValue() const; 253 254 private: 255 // See comment of ::RegisterThread() for details. 256 [[nodiscard]] ScopedClosureRunner RegisterThreadInternal( 257 ThreadType thread_type) LOCKS_EXCLUDED(watch_state_lock_); 258 259 // Use to assert that functions are called on the monitoring thread. 260 THREAD_CHECKER(hang_watcher_thread_checker_); 261 262 // Use to assert that functions are called on the constructing thread. 263 THREAD_CHECKER(constructing_thread_checker_); 264 265 // Invoked on memory pressure signal. 266 void OnMemoryPressure( 267 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); 268 269 #if !BUILDFLAG(IS_NACL) 270 // Returns a ScopedCrashKeyString that sets the crash key with the time since 271 // last critical memory pressure signal. 272 [[nodiscard]] debug::ScopedCrashKeyString 273 GetTimeSinceLastCriticalMemoryPressureCrashKey(); 274 #endif 275 276 // Invoke base::debug::DumpWithoutCrashing() insuring that the stack frame 277 // right under it in the trace belongs to HangWatcher for easier attribution. 278 NOINLINE static void RecordHang(); 279 280 using HangWatchStates = 281 std::vector<std::unique_ptr<internal::HangWatchState>>; 282 283 // Used to save a snapshots of the state of hang watching during capture. 284 // Only the state of hung threads is retained. 285 class BASE_EXPORT WatchStateSnapShot { 286 public: 287 struct WatchStateCopy { 288 base::TimeTicks deadline; 289 base::PlatformThreadId thread_id; 290 }; 291 292 WatchStateSnapShot(); 293 WatchStateSnapShot(const WatchStateSnapShot& other); 294 ~WatchStateSnapShot(); 295 296 // Initialize the snapshot from provided data. |snapshot_time| can be 297 // different than now() to be coherent with other operations recently done 298 // on |watch_states|. |hung_watch_state_copies_| can be empty after 299 // initialization for a number of reasons: 300 // 1. If any deadline in |watch_states| is before 301 // |deadline_ignore_threshold|. 302 // 2. If some of the hung threads could not be marked as blocking on 303 // capture. 304 // 3. If none of the hung threads are of a type configured to trigger a 305 // crash dump. 306 // 307 // This function cannot be called more than once without an associated call 308 // to Clear(). 309 void Init(const HangWatchStates& watch_states, 310 base::TimeTicks deadline_ignore_threshold); 311 312 // Reset the snapshot object to be reused. Can only be called after Init(). 313 void Clear(); 314 315 // Returns a string that contains the ids of the hung threads separated by a 316 // '|'. The size of the string is capped at debug::CrashKeySize::Size256. If 317 // no threads are hung returns an empty string. Can only be invoked if 318 // IsActionable(). Can only be called after Init(). 319 std::string PrepareHungThreadListCrashKey() const; 320 321 // Return the highest deadline included in this snapshot. Can only be called 322 // if IsActionable(). Can only be called after Init(). 323 base::TimeTicks GetHighestDeadline() const; 324 325 // Returns true if the snapshot can be used to record an actionable hang 326 // report and false if not. Can only be called after Init(). 327 bool IsActionable() const; 328 329 private: 330 bool initialized_ = false; 331 std::vector<WatchStateCopy> hung_watch_state_copies_; 332 }; 333 334 // Return a watch state snapshot taken Now() to be inspected in tests. 335 // NO_THREAD_SAFETY_ANALYSIS is needed because the analyzer can't figure out 336 // that calls to this function done from |on_hang_closure_| are properly 337 // locked. 338 WatchStateSnapShot GrabWatchStateSnapshotForTesting() const 339 NO_THREAD_SAFETY_ANALYSIS; 340 341 // Inspects the state of all registered threads to check if they are hung and 342 // invokes the appropriate closure if so. 343 void Monitor() LOCKS_EXCLUDED(watch_state_lock_); 344 345 // Record the hang crash dump and perform the necessary housekeeping before 346 // and after. 347 void DoDumpWithoutCrashing(const WatchStateSnapShot& watch_state_snapshot) 348 EXCLUSIVE_LOCKS_REQUIRED(watch_state_lock_) LOCKS_EXCLUDED(capture_lock_); 349 350 // Stop all monitoring and join the HangWatcher thread. 351 void Stop(); 352 353 // Wait until it's time to monitor. 354 void Wait(); 355 356 // Run the loop that periodically monitors the registered thread at a 357 // set time interval. 358 void Run() override; 359 360 base::TimeDelta monitor_period_; 361 362 // Use to make the HangWatcher thread wake or sleep to schedule the 363 // appropriate monitoring frequency. 364 WaitableEvent should_monitor_; 365 366 bool IsWatchListEmpty() LOCKS_EXCLUDED(watch_state_lock_); 367 368 // Stops hang watching on the calling thread by removing the entry from the 369 // watch list. 370 void UnregisterThread() LOCKS_EXCLUDED(watch_state_lock_); 371 372 Lock watch_state_lock_; 373 374 std::vector<std::unique_ptr<internal::HangWatchState>> watch_states_ 375 GUARDED_BY(watch_state_lock_); 376 377 // Snapshot to be reused across hang captures. The point of keeping it 378 // around is reducing allocations during capture. 379 WatchStateSnapShot watch_state_snapshot_ 380 GUARDED_BY_CONTEXT(hang_watcher_thread_checker_); 381 382 base::DelegateSimpleThread thread_; 383 384 RepeatingClosure after_monitor_closure_for_testing_; 385 RepeatingClosure on_hang_closure_for_testing_; 386 RepeatingCallback<void(TimeTicks)> after_wait_callback_; 387 388 base::Lock capture_lock_ ACQUIRED_AFTER(watch_state_lock_); 389 std::atomic<bool> capture_in_progress_{false}; 390 391 raw_ptr<const base::TickClock> tick_clock_; 392 393 // Registration to receive memory pressure signals. 394 base::MemoryPressureListener memory_pressure_listener_; 395 396 // The last time at which a critical memory pressure signal was received, or 397 // null if no signal was ever received. Atomic because it's set and read from 398 // different threads. 399 std::atomic<base::TimeTicks> last_critical_memory_pressure_{ 400 base::TimeTicks()}; 401 402 // The time after which all deadlines in |watch_states_| need to be for a hang 403 // to be reported. 404 base::TimeTicks deadline_ignore_threshold_; 405 406 FRIEND_TEST_ALL_PREFIXES(HangWatcherTest, NestedScopes); 407 FRIEND_TEST_ALL_PREFIXES(HangWatcherSnapshotTest, HungThreadIDs); 408 FRIEND_TEST_ALL_PREFIXES(HangWatcherSnapshotTest, NonActionableReport); 409 }; 410 411 // Classes here are exposed in the header only for testing. They are not 412 // intended to be used outside of base. 413 namespace internal { 414 415 // Threadsafe class that manages a deadline of type TimeTicks alongside hang 416 // watching specific flags. The flags are stored in the higher bits of the 417 // underlying TimeTicks deadline. This enables setting the flags on thread T1 in 418 // a way that's resilient to concurrent deadline or flag changes from thread T2. 419 // Flags can be queried separately from the deadline and users of this class 420 // should not have to care about them when doing so. 421 class BASE_EXPORT HangWatchDeadline { 422 public: 423 // Masks to set flags by flipping a single bit in the TimeTicks value. There 424 // are two types of flags. Persistent flags remain set through a deadline 425 // change and non-persistent flags are cleared when the deadline changes. 426 enum class Flag : uint64_t { 427 // Minimum value for validation purposes. Not currently used. 428 kMinValue = bits::LeftmostBit<uint64_t>() >> 7, 429 // Persistent because if hang detection is disabled on a thread it should 430 // be re-enabled manually. 431 kIgnoreCurrentWatchHangsInScope = bits::LeftmostBit<uint64_t>() >> 1, 432 // Non-persistent because a new value means a new WatchHangsInScope started 433 // after the beginning of capture. It can't be implicated in the hang so we 434 // don't want it to block. 435 kShouldBlockOnHang = bits::LeftmostBit<uint64_t>() >> 0, 436 kMaxValue = kShouldBlockOnHang 437 }; 438 439 HangWatchDeadline(); 440 ~HangWatchDeadline(); 441 442 // HangWatchDeadline should never be copied. To keep a copy of the deadline or 443 // flags use the appropriate accessors. 444 HangWatchDeadline(const HangWatchDeadline&) = delete; 445 HangWatchDeadline& operator=(const HangWatchDeadline&) = delete; 446 447 // Returns the underlying TimeTicks deadline. WARNING: The deadline and flags 448 // can change concurrently. To inspect both, use GetFlagsAndDeadline() to get 449 // a coherent race-free view of the state. 450 TimeTicks GetDeadline() const; 451 452 // Returns a mask containing the flags and the deadline as a pair. Use to 453 // inspect the flags and deadline and then optionally call 454 // SetShouldBlockOnHang() . 455 std::pair<uint64_t, TimeTicks> GetFlagsAndDeadline() const; 456 457 // Returns true if the flag is set and false if not. WARNING: The deadline and 458 // flags can change concurrently. To inspect both, use GetFlagsAndDeadline() 459 // to get a coherent race-free view of the state. 460 bool IsFlagSet(Flag flag) const; 461 462 // Returns true if a flag is set in |flags| and false if not. Use to inspect 463 // the flags mask returned by GetFlagsAndDeadline(). WARNING: The deadline and 464 // flags can change concurrently. If you need to inspect both you need to use 465 // GetFlagsAndDeadline() to get a coherent race-free view of the state. 466 static bool IsFlagSet(Flag flag, uint64_t flags); 467 468 // Replace the deadline value. |new_value| needs to be within [0, 469 // Max()]. This function can never fail. 470 void SetDeadline(TimeTicks new_value); 471 472 // Sets the kShouldBlockOnHang flag and returns true if current flags and 473 // deadline are still equal to |old_flags| and |old_deadline|. Otherwise does 474 // not set the flag and returns false. 475 bool SetShouldBlockOnHang(uint64_t old_flags, TimeTicks old_deadline); 476 477 // Sets the kIgnoreCurrentWatchHangsInScope flag. 478 void SetIgnoreCurrentWatchHangsInScope(); 479 480 // Clears the kIgnoreCurrentWatchHangsInScope flag. 481 void UnsetIgnoreCurrentWatchHangsInScope(); 482 483 // Use to simulate the value of |bits_| changing between the calling a 484 // Set* function and the moment of atomically switching the values. The 485 // callback should return a value containing the desired flags and deadline 486 // bits. The flags that are already set will be preserved upon applying. Use 487 // only for testing. 488 void SetSwitchBitsClosureForTesting( 489 RepeatingCallback<uint64_t(void)> closure); 490 491 // Remove the deadline modification callback for when testing is done. Use 492 // only for testing. 493 void ResetSwitchBitsClosureForTesting(); 494 495 private: 496 using TimeTicksInternalRepresentation = 497 std::invoke_result<decltype(&TimeTicks::ToInternalValue), 498 TimeTicks>::type; 499 static_assert(std::is_same<TimeTicksInternalRepresentation, int64_t>::value, 500 "Bit manipulations made by HangWatchDeadline need to be" 501 "adapted if internal representation of TimeTicks changes."); 502 503 // Replace the bits with the ones provided through the callback. Preserves the 504 // flags that were already set. Returns the switched in bits. Only call if 505 // |switch_bits_callback_for_testing_| is installed. 506 uint64_t SwitchBitsForTesting(); 507 508 // Atomically sets persitent flag |flag|. Cannot fail. 509 void SetPersistentFlag(Flag flag); 510 511 // Atomically clears persitent flag |flag|. Cannot fail. 512 void ClearPersistentFlag(Flag flag); 513 514 // Converts bits to TimeTicks with some sanity checks. Use to return the 515 // deadline outside of this class. 516 static TimeTicks DeadlineFromBits(uint64_t bits); 517 518 // Returns the largest representable deadline. 519 static TimeTicks Max(); 520 521 // Extract the flag bits from |bits|. 522 static uint64_t ExtractFlags(uint64_t bits); 523 524 // Extract the deadline bits from |bits|. 525 static uint64_t ExtractDeadline(uint64_t bits); 526 527 // BitsType is uint64_t. This type is chosen for having 528 // std::atomic<BitsType>{}.is_lock_free() true on many platforms and having no 529 // undefined behaviors with regards to bit shift operations. Throughout this 530 // class this is the only type that is used to store, retrieve and manipulate 531 // the bits. When returning a TimeTicks value outside this class it's 532 // necessary to run the proper checks to insure correctness of the conversion 533 // that has to go through int_64t. (See DeadlineFromBits()). 534 using BitsType = uint64_t; 535 static_assert(std::is_same<std::underlying_type<Flag>::type, BitsType>::value, 536 "Flag should have the same underlying type as bits_ to " 537 "simplify thinking about bit operations"); 538 539 // Holds the bits of both the flags and the TimeTicks deadline. 540 // TimeTicks values represent a count of microseconds since boot which may or 541 // may not include suspend time depending on the platform. Using the seven 542 // highest order bits and the sign bit to store flags still enables the 543 // storing of TimeTicks values that can represent up to ~1142 years of uptime 544 // in the remaining bits. Should never be directly accessed from outside the 545 // class. Starts out at Max() to provide a base-line deadline that will not be 546 // reached during normal execution. 547 // 548 // Binary format: 0xFFDDDDDDDDDDDDDDDD 549 // F = Flags 550 // D = Deadline 551 std::atomic<BitsType> bits_{static_cast<uint64_t>(Max().ToInternalValue())}; 552 553 RepeatingCallback<uint64_t(void)> switch_bits_callback_for_testing_; 554 555 THREAD_CHECKER(thread_checker_); 556 557 FRIEND_TEST_ALL_PREFIXES(HangWatchDeadlineTest, BitsPreservedThroughExtract); 558 }; 559 560 // Contains the information necessary for hang watching a specific 561 // thread. Instances of this class are accessed concurrently by the associated 562 // thread and the HangWatcher. The HangWatcher owns instances of this 563 // class and outside of it they are accessed through 564 // GetHangWatchStateForCurrentThread(). 565 class BASE_EXPORT HangWatchState { 566 public: 567 // |thread_type| is the type of thread the watch state will 568 // be associated with. It's the responsibility of the creating 569 // code to choose the correct type. 570 explicit HangWatchState(HangWatcher::ThreadType thread_type); 571 ~HangWatchState(); 572 573 HangWatchState(const HangWatchState&) = delete; 574 HangWatchState& operator=(const HangWatchState&) = delete; 575 576 // Allocates a new state object bound to the calling thread and returns an 577 // owning pointer to it. 578 static std::unique_ptr<HangWatchState> CreateHangWatchStateForCurrentThread( 579 HangWatcher::ThreadType thread_type); 580 581 // Retrieves the hang watch state associated with the calling thread. 582 // Returns nullptr if no HangWatchState exists for the current thread (see 583 // CreateHangWatchStateForCurrentThread()). 584 static HangWatchState* GetHangWatchStateForCurrentThread(); 585 586 // Returns the current deadline. Use this function if you need to 587 // store the value. To test if the deadline has expired use IsOverDeadline(). 588 // WARNING: The deadline and flags can change concurrently. If you need to 589 // inspect both you need to use GetFlagsAndDeadline() to get a coherent 590 // race-free view of the state. 591 TimeTicks GetDeadline() const; 592 593 // Returns a mask containing the hang watching flags and the value as a pair. 594 // Use to inspect the flags and deadline and optionally call 595 // SetShouldBlockOnHang(flags, deadline). 596 std::pair<uint64_t, TimeTicks> GetFlagsAndDeadline() const; 597 598 // Sets the deadline to a new value. 599 void SetDeadline(TimeTicks deadline); 600 601 // Mark this thread as ignored for hang watching. This means existing 602 // WatchHangsInScope will not trigger hangs. 603 void SetIgnoreCurrentWatchHangsInScope(); 604 605 // Reactivate hang watching on this thread. Should be called when all 606 // WatchHangsInScope instances that were ignored have completed. 607 void UnsetIgnoreCurrentWatchHangsInScope(); 608 609 // Mark the current state as having to block in its destruction until hang 610 // capture completes. 611 bool SetShouldBlockOnHang(uint64_t old_flags, TimeTicks old_deadline); 612 613 // Returns true if |flag| is set and false if not. WARNING: The deadline and 614 // flags can change concurrently. If you need to inspect both you need to use 615 // GetFlagsAndDeadline() to get a coherent race-free view of the state. 616 bool IsFlagSet(HangWatchDeadline::Flag flag); 617 618 // Tests whether the associated thread's execution has gone over the deadline. 619 bool IsOverDeadline() const; 620 621 #if DCHECK_IS_ON() 622 // Saves the supplied WatchHangsInScope as the currently active 623 // WatchHangsInScope. 624 void SetCurrentWatchHangsInScope(WatchHangsInScope* scope); 625 626 // Retrieve the currently active scope. 627 WatchHangsInScope* GetCurrentWatchHangsInScope(); 628 #endif 629 630 PlatformThreadId GetThreadID() const; 631 632 // Retrieve the current hang watch deadline directly. For testing only. 633 HangWatchDeadline* GetHangWatchDeadlineForTesting(); 634 635 // Returns the current nesting level. nesting_level()636 int nesting_level() { return nesting_level_; } 637 638 // Increase the nesting level by 1; 639 void IncrementNestingLevel(); 640 641 // Reduce the nesting level by 1; 642 void DecrementNestingLevel(); 643 644 // Returns the type of the thread under watch. thread_type()645 HangWatcher::ThreadType thread_type() const { return thread_type_; } 646 647 private: 648 // The thread that creates the instance should be the class that updates 649 // the deadline. 650 THREAD_CHECKER(thread_checker_); 651 652 const AutoReset<HangWatchState*> resetter_; 653 654 // If the deadline fails to be updated before TimeTicks::Now() ever 655 // reaches the value contained in it this constistutes a hang. 656 HangWatchDeadline deadline_; 657 658 // A unique ID of the thread under watch. Used for logging in crash reports 659 // only. 660 PlatformThreadId thread_id_; 661 662 // Number of active HangWatchScopeEnables on this thread. 663 int nesting_level_ = 0; 664 665 // The type of the thread under watch. 666 const HangWatcher::ThreadType thread_type_; 667 668 #if DCHECK_IS_ON() 669 // Used to keep track of the current WatchHangsInScope and detect improper 670 // usage. Scopes should always be destructed in reverse order from the one 671 // they were constructed in. Example of improper use: 672 // 673 // { 674 // std::unique_ptr<Scope> scope = std::make_unique<Scope>(...); 675 // Scope other_scope; 676 // |scope| gets deallocated first, violating reverse destruction order. 677 // scope.reset(); 678 // } 679 raw_ptr<WatchHangsInScope> current_watch_hangs_in_scope_{nullptr}; 680 #endif 681 }; 682 683 } // namespace internal 684 } // namespace base 685 686 #endif // BASE_THREADING_HANG_WATCHER_H_ 687