xref: /aosp_15_r20/external/cronet/base/threading/hang_watcher.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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