// Copyright 2020 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #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/auto_reset.h" #include "base/base_export.h" #include "base/bits.h" #include "base/compiler_specific.h" #include "base/dcheck_is_on.h" #include "base/debug/crash_logging.h" #include "base/functional/callback.h" #include "base/functional/callback_forward.h" #include "base/functional/callback_helpers.h" #include "base/gtest_prod_util.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/raw_ptr.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.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/time/tick_clock.h" #include "base/time/time.h" #include "build/build_config.h" namespace base { class WatchHangsInScope; namespace internal { class HangWatchState; } // namespace internal } // namespace base namespace base { // Instantiate a WatchHangsInScope in a code scope to register to be // watched for hangs of more than |timeout| by the HangWatcher. // // Example usage: // // void FooBar(){ // WatchHangsInScope scope(base::Seconds(5)); // DoWork(); // } // // If DoWork() takes more than 5s to run and the HangWatcher // inspects the thread state before Foobar returns a hang will be // reported. // // WatchHangsInScopes are typically meant to live on the stack. In some // cases it's necessary to keep a WatchHangsInScope instance as a class // member but special care is required when doing so as a WatchHangsInScope // that stays alive longer than intended will generate non-actionable hang // reports. class BASE_EXPORT [[maybe_unused, nodiscard]] WatchHangsInScope { … }; // Monitors registered threads for hangs by inspecting their associated // HangWatchStates for deadline overruns. This happens at a regular interval on // a separate thread. Only one instance of HangWatcher can exist at a time // within a single process. This instance must outlive all monitored threads. class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { … }; // Classes here are exposed in the header only for testing. They are not // intended to be used outside of base. namespace internal { // Threadsafe class that manages a deadline of type TimeTicks alongside hang // watching specific flags. The flags are stored in the higher bits of the // underlying TimeTicks deadline. This enables setting the flags on thread T1 in // a way that's resilient to concurrent deadline or flag changes from thread T2. // Flags can be queried separately from the deadline and users of this class // should not have to care about them when doing so. class BASE_EXPORT HangWatchDeadline { … }; // Contains the information necessary for hang watching a specific // thread. Instances of this class are accessed concurrently by the associated // thread and the HangWatcher. The HangWatcher owns instances of this // class and outside of it they are accessed through // GetHangWatchStateForCurrentThread(). class BASE_EXPORT HangWatchState { … }; } // namespace internal } // namespace base #endif // BASE_THREADING_HANG_WATCHER_H_