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