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