123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 |
- #ifndef BASE_THREADING_HANG_WATCHER_H_
- #define BASE_THREADING_HANG_WATCHER_H_
- #include <atomic>
- #include <cstdint>
- #include <memory>
- #include <type_traits>
- #include <vector>
- #include "base/atomicops.h"
- #include "base/bits.h"
- #include "base/callback.h"
- #include "base/callback_forward.h"
- #include "base/callback_helpers.h"
- #include "base/compiler_specific.h"
- #include "base/synchronization/lock.h"
- #include "base/thread_annotations.h"
- #include "base/threading/platform_thread.h"
- #include "base/threading/simple_thread.h"
- #include "base/threading/thread_checker.h"
- #include "base/threading/thread_local.h"
- #include "base/time/tick_clock.h"
- #include "base/time/time.h"
- namespace base {
- class HangWatchScopeEnabled;
- namespace internal {
- class HangWatchState;
- }
- }
- namespace base {
- class BASE_EXPORT HangWatchScopeEnabled {
- public:
-
-
-
-
-
- static const base::TimeDelta kDefaultHangWatchTime;
-
- explicit HangWatchScopeEnabled(TimeDelta timeout);
- ~HangWatchScopeEnabled();
- HangWatchScopeEnabled(const HangWatchScopeEnabled&) = delete;
- HangWatchScopeEnabled& operator=(const HangWatchScopeEnabled&) = delete;
- private:
-
- THREAD_CHECKER(thread_checker_);
-
-
-
- TimeTicks previous_deadline_;
-
-
-
-
-
- bool set_hangs_ignored_on_exit_ = false;
- #if DCHECK_IS_ON()
-
- HangWatchScopeEnabled* previous_hang_watch_scope_enable_;
- #endif
- };
- class BASE_EXPORT HangWatchScopeDisabled {
- public:
- HangWatchScopeDisabled();
- ~HangWatchScopeDisabled();
- HangWatchScopeDisabled(const HangWatchScopeDisabled&) = delete;
- HangWatchScopeDisabled& operator=(const HangWatchScopeDisabled&) = delete;
- };
- class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate {
- public:
-
-
-
- HangWatcher();
-
- ~HangWatcher() override;
- HangWatcher(const HangWatcher&) = delete;
- HangWatcher& operator=(const HangWatcher&) = delete;
-
- static HangWatcher* GetInstance();
-
-
- static void InitializeOnMainThread();
-
-
- static bool IsEnabled();
- static bool IsThreadPoolHangWatchingEnabled();
- static bool IsIOThreadHangWatchingEnabled();
- static bool IsUIThreadHangWatchingEnabled();
-
-
-
- ScopedClosureRunner RegisterThread()
- LOCKS_EXCLUDED(watch_state_lock_) WARN_UNUSED_RESULT;
-
-
-
-
- void SetAfterMonitorClosureForTesting(base::RepeatingClosure closure);
-
-
-
-
-
- void SetOnHangClosureForTesting(base::RepeatingClosure closure);
-
-
- void SetMonitoringPeriodForTesting(base::TimeDelta period);
-
-
- void SetAfterWaitCallbackForTesting(
- RepeatingCallback<void(TimeTicks)> callback);
-
-
-
- void SignalMonitorEventForTesting();
-
-
-
- void StopMonitoringForTesting();
-
-
- void SetTickClockForTesting(const base::TickClock* tick_clock);
-
-
-
- void BlockIfCaptureInProgress();
-
- void Start();
- private:
-
- THREAD_CHECKER(hang_watcher_thread_checker_);
-
- THREAD_CHECKER(constructing_thread_checker_);
-
-
- NOINLINE static void RecordHang();
- using HangWatchStates =
- std::vector<std::unique_ptr<internal::HangWatchState>>;
-
-
- class BASE_EXPORT WatchStateSnapShot {
- public:
- struct WatchStateCopy {
- base::TimeTicks deadline;
- base::PlatformThreadId thread_id;
- };
-
-
-
-
- WatchStateSnapShot(const HangWatchStates& watch_states,
- base::TimeTicks snapshot_time,
- base::TimeTicks deadline_ignore_threshold);
- WatchStateSnapShot(const WatchStateSnapShot& other);
- ~WatchStateSnapShot();
-
-
-
-
- std::string PrepareHungThreadListCrashKey() const;
-
- base::TimeTicks GetHighestDeadline() const;
-
-
- bool IsActionable() const;
- private:
- base::TimeTicks snapshot_time_;
- std::vector<WatchStateCopy> hung_watch_state_copies_;
- };
-
-
-
-
- WatchStateSnapShot GrabWatchStateSnapshotForTesting() const
- NO_THREAD_SAFETY_ANALYSIS;
-
-
- void Monitor() LOCKS_EXCLUDED(watch_state_lock_);
-
- void CaptureHang(base::TimeTicks capture_time)
- EXCLUSIVE_LOCKS_REQUIRED(watch_state_lock_) LOCKS_EXCLUDED(capture_lock_);
-
- void Stop();
-
- void Wait();
-
-
- void Run() override;
- base::TimeDelta monitor_period_;
-
- std::atomic<bool> keep_monitoring_{true};
-
-
- WaitableEvent should_monitor_;
- bool IsWatchListEmpty() LOCKS_EXCLUDED(watch_state_lock_);
-
-
- void UnregisterThread() LOCKS_EXCLUDED(watch_state_lock_);
- Lock watch_state_lock_;
- std::vector<std::unique_ptr<internal::HangWatchState>> watch_states_
- GUARDED_BY(watch_state_lock_);
- base::DelegateSimpleThread thread_;
- RepeatingClosure after_monitor_closure_for_testing_;
- RepeatingClosure on_hang_closure_for_testing_;
- RepeatingCallback<void(TimeTicks)> after_wait_callback_;
- base::Lock capture_lock_ ACQUIRED_AFTER(watch_state_lock_);
- std::atomic<bool> capture_in_progress_{false};
- const base::TickClock* tick_clock_;
-
-
- base::TimeTicks deadline_ignore_threshold_;
- FRIEND_TEST_ALL_PREFIXES(HangWatcherTest, NestedScopes);
- FRIEND_TEST_ALL_PREFIXES(HangWatcherSnapshotTest, HungThreadIDs);
- FRIEND_TEST_ALL_PREFIXES(HangWatcherSnapshotTest, NonActionableReport);
- };
- namespace internal {
- class BASE_EXPORT HangWatchDeadline {
- public:
-
-
-
- enum class Flag : uint64_t {
-
- kMinValue = bits::LeftmostBit<uint64_t>() >> 7,
-
- kHasActiveHangWatchScopeDisabled = bits::LeftmostBit<uint64_t>() >> 2,
-
-
- kIgnoreCurrentHangWatchScopeEnabled = bits::LeftmostBit<uint64_t>() >> 1,
-
-
-
-
- kShouldBlockOnHang = bits::LeftmostBit<uint64_t>() >> 0,
- kMaxValue = kShouldBlockOnHang
- };
- HangWatchDeadline();
- ~HangWatchDeadline();
-
-
- HangWatchDeadline(const HangWatchDeadline&) = delete;
- HangWatchDeadline& operator=(const HangWatchDeadline&) = delete;
-
-
-
- TimeTicks GetDeadline() const;
-
-
-
- std::pair<uint64_t, TimeTicks> GetFlagsAndDeadline() const;
-
-
-
- bool IsFlagSet(Flag flag) const;
-
-
-
-
- static bool IsFlagSet(Flag flag, uint64_t flags);
-
-
- void SetDeadline(TimeTicks new_value);
-
-
-
- bool SetShouldBlockOnHang(uint64_t old_flags, TimeTicks old_deadline);
-
- void SetHasActiveHangWatchScopeDisabled();
-
- void UnsetHasActiveHangWatchScopeDisabled();
-
- void SetIgnoreCurrentHangWatchScopeEnabled();
-
- void UnsetIgnoreCurrentHangWatchScopeEnabled();
-
-
-
-
-
- void SetSwitchBitsClosureForTesting(
- RepeatingCallback<uint64_t(void)> closure);
-
-
- void ResetSwitchBitsClosureForTesting();
- private:
- using TimeTicksInternalRepresentation =
- std::result_of<decltype (&TimeTicks::ToInternalValue)(TimeTicks)>::type;
- static_assert(std::is_same<TimeTicksInternalRepresentation, int64_t>::value,
- "Bit manipulations made by HangWatchDeadline need to be"
- "adapted if internal representation of TimeTicks changes.");
-
-
-
- uint64_t SwitchBitsForTesting();
-
- void SetPersistentFlag(Flag flag);
-
- void ClearPersistentFlag(Flag flag);
-
-
- static TimeTicks DeadlineFromBits(uint64_t bits);
-
- static TimeTicks Max();
-
- static uint64_t ExtractFlags(uint64_t bits);
-
- static uint64_t ExtractDeadline(uint64_t bits);
-
-
-
-
-
-
-
- using BitsType = uint64_t;
- static_assert(std::is_same<std::underlying_type<Flag>::type, BitsType>::value,
- "Flag should have the same underlying type as bits_ to "
- "simplify thinking about bit operations");
-
-
-
-
-
-
-
-
-
-
-
-
- std::atomic<BitsType> bits_{static_cast<uint64_t>(Max().ToInternalValue())};
- RepeatingCallback<uint64_t(void)> switch_bits_callback_for_testing_;
- THREAD_CHECKER(thread_checker_);
- FRIEND_TEST_ALL_PREFIXES(HangWatchDeadlineTest, BitsPreservedThroughExtract);
- };
- class BASE_EXPORT HangWatchState {
- public:
- HangWatchState();
- ~HangWatchState();
- HangWatchState(const HangWatchState&) = delete;
- HangWatchState& operator=(const HangWatchState&) = delete;
-
-
- static std::unique_ptr<HangWatchState> CreateHangWatchStateForCurrentThread();
-
-
-
- static ThreadLocalPointer<HangWatchState>*
- GetHangWatchStateForCurrentThread();
-
-
-
-
-
- TimeTicks GetDeadline() const;
-
-
-
- std::pair<uint64_t, TimeTicks> GetFlagsAndDeadline() const;
-
- void SetDeadline(TimeTicks deadline);
-
-
- void SetIgnoreCurrentHangWatchScopeEnabled();
-
-
- void UnsetIgnoreCurrentHangWatchScopeEnabled();
-
-
- void SetHasActiveHangWatchScopeDisabled();
-
-
- void UnsetHasActiveHangWatchScopeDisabled();
-
-
- bool SetShouldBlockOnHang(uint64_t old_flags, TimeTicks old_deadline);
-
-
-
- bool IsFlagSet(HangWatchDeadline::Flag flag);
-
- bool IsOverDeadline() const;
- #if DCHECK_IS_ON()
-
-
- void SetCurrentHangWatchScopeEnabled(HangWatchScopeEnabled* scope);
-
- HangWatchScopeEnabled* GetCurrentHangWatchScopeEnabled();
- #endif
- PlatformThreadId GetThreadID() const;
-
- HangWatchDeadline* GetHangWatchDeadlineForTesting();
-
- int nesting_level() { return nesting_level_; }
-
- void IncrementNestingLevel();
-
- void DecrementNestingLevel();
- private:
-
-
- THREAD_CHECKER(thread_checker_);
-
-
- HangWatchDeadline deadline_;
- const PlatformThreadId thread_id_;
-
- int nesting_level_ = 0;
- #if DCHECK_IS_ON()
-
-
-
-
-
-
-
-
-
-
- HangWatchScopeEnabled* current_hang_watch_scope_enable_{nullptr};
- #endif
- };
- }
- }
- #endif
|