1 // Copyright 2012 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 // The Watchdog class creates a second thread that can Alarm if a specific 6 // duration of time passes without proper attention. The duration of time is 7 // specified at construction time. The Watchdog may be used many times by 8 // simply calling Arm() (to start timing) and Disarm() (to reset the timer). 9 // The Watchdog is typically used under a debugger, where the stack traces on 10 // other threads can be examined if/when the Watchdog alarms. 11 12 // Some watchdogs will be enabled or disabled via command line switches. To 13 // facilitate such code, an "enabled" argument for the constuctor can be used 14 // to permanently disable the watchdog. Disabled watchdogs don't even spawn 15 // a second thread, and their methods call (Arm() and Disarm()) return very 16 // quickly. 17 18 #ifndef BASE_THREADING_WATCHDOG_H_ 19 #define BASE_THREADING_WATCHDOG_H_ 20 21 #include <string> 22 23 #include "base/base_export.h" 24 #include "base/compiler_specific.h" 25 #include "base/memory/raw_ptr.h" 26 #include "base/synchronization/condition_variable.h" 27 #include "base/synchronization/lock.h" 28 #include "base/threading/platform_thread.h" 29 #include "base/time/time.h" 30 31 namespace base { 32 33 class BASE_EXPORT Watchdog { 34 public: 35 class Delegate { 36 public: 37 virtual ~Delegate() = default; 38 39 // Called on the watchdog thread. 40 virtual void Alarm() = 0; 41 }; 42 43 // Constructor specifies how long the Watchdog will wait before alarming. If 44 // `delegate` is non-null, `Alarm` on the delegate will be called instead of 45 // the default behavior. 46 Watchdog(const TimeDelta& duration, 47 const std::string& thread_watched_name, 48 bool enabled, 49 Delegate* delegate = nullptr); 50 51 Watchdog(const Watchdog&) = delete; 52 Watchdog& operator=(const Watchdog&) = delete; 53 54 ~Watchdog(); 55 56 // Notify watchdog thread to finish up. Sets the state_ to SHUTDOWN. 57 void Cleanup(); 58 59 // Returns true if we state_ is JOINABLE (which indicates that Watchdog has 60 // exited). 61 bool IsJoinable(); 62 63 // Start timing, and alarm when time expires (unless we're disarm()ed.) 64 void Arm(); // Arm starting now. 65 void ArmSomeTimeDeltaAgo(const TimeDelta& time_delta); 66 void ArmAtStartTime(const TimeTicks start_time); 67 68 // Reset time, and do not set off the alarm. 69 void Disarm(); 70 71 // Alarm is called if the time expires after an Arm() without someone calling 72 // Disarm(). 73 void Alarm(); 74 75 // Reset static data to initial state. Useful for tests, to ensure 76 // they are independent. 77 static void ResetStaticData(); 78 79 // The default behavior of Alarm() if a delegate is not provided. 80 void DefaultAlarm(); 81 82 private: 83 class ThreadDelegate : public PlatformThread::Delegate { 84 public: ThreadDelegate(Watchdog * watchdog)85 explicit ThreadDelegate(Watchdog* watchdog) : watchdog_(watchdog) { 86 } 87 void ThreadMain() override; 88 89 private: 90 void SetThreadName() const; 91 92 raw_ptr<Watchdog> watchdog_; 93 }; 94 95 enum State { ARMED, DISARMED, SHUTDOWN, JOINABLE }; 96 97 bool enabled_; 98 99 Lock lock_; 100 ConditionVariable condition_variable_; 101 State state_ GUARDED_BY(lock_); 102 const TimeDelta duration_; // How long after start_time_ do we alarm? 103 const std::string thread_watched_name_; 104 PlatformThreadHandle handle_; 105 ThreadDelegate thread_delegate_; // Must outlive the thread. 106 107 raw_ptr<Delegate> delegate_; 108 TimeTicks start_time_; // Start of epoch, and alarm after duration_. 109 }; 110 111 } // namespace base 112 113 #endif // BASE_THREADING_WATCHDOG_H_ 114