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