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