#include "base/threading/hang_watcher.h"
#include <atomic>
#include <utility>
#include "base/containers/flat_map.h"
#include "base/debug/alias.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/debug/leak_annotations.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/power_monitor/power_monitor.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/threading_features.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"
#include "third_party/abseil-cpp/absl/base/attributes.h"
namespace base {
namespace {
enum class LoggingLevel { … };
HangWatcher* g_instance = …;
ABSL_CONST_INIT thread_local internal::HangWatchState* hang_watch_state = …;
std::atomic<bool> g_use_hang_watcher{ … };
std::atomic<HangWatcher::ProcessType> g_hang_watcher_process_type{ … };
std::atomic<LoggingLevel> g_threadpool_log_level{ … };
std::atomic<LoggingLevel> g_io_thread_log_level{ … };
std::atomic<LoggingLevel> g_main_thread_log_level{ … };
std::atomic<bool> g_keep_monitoring{ … };
std::atomic<bool> g_shutting_down{ … };
void LogStatusHistogram(HangWatcher::ThreadType thread_type,
int count,
TimeTicks sample_ticks,
TimeDelta monitoring_period) { … }
bool ThreadTypeLoggingLevelGreaterOrEqual(HangWatcher::ThreadType thread_type,
LoggingLevel logging_level) { … }
}
BASE_FEATURE(…);
BASE_FEATURE(…);
constexpr base::FeatureParam<int> kIOThreadLogLevel{ … };
constexpr base::FeatureParam<int> kUIThreadLogLevel{ … };
constexpr base::FeatureParam<int> kThreadPoolLogLevel{ … };
constexpr base::FeatureParam<int> kGPUProcessIOThreadLogLevel{ … };
constexpr base::FeatureParam<int> kGPUProcessMainThreadLogLevel{ … };
constexpr base::FeatureParam<int> kGPUProcessThreadPoolLogLevel{ … };
constexpr base::FeatureParam<int> kRendererProcessIOThreadLogLevel{ … };
constexpr base::FeatureParam<int> kRendererProcessMainThreadLogLevel{ … };
constexpr base::FeatureParam<int> kRendererProcessThreadPoolLogLevel{ … };
constexpr base::FeatureParam<int> kUtilityProcessIOThreadLogLevel{ … };
constexpr base::FeatureParam<int> kUtilityProcessMainThreadLogLevel{ … };
constexpr base::FeatureParam<int> kUtilityProcessThreadPoolLogLevel{ … };
constexpr const char* kThreadName = …;
constexpr auto kMonitoringPeriod = …;
WatchHangsInScope::WatchHangsInScope(TimeDelta timeout) { … }
WatchHangsInScope::~WatchHangsInScope() { … }
void HangWatcher::InitializeOnMainThread(ProcessType process_type,
bool is_zygote_child,
bool emit_crashes) { … }
void HangWatcher::UnitializeOnMainThreadForTesting() { … }
bool HangWatcher::IsEnabled() { … }
bool HangWatcher::IsThreadPoolHangWatchingEnabled() { … }
bool HangWatcher::IsIOThreadHangWatchingEnabled() { … }
bool HangWatcher::IsCrashReportingEnabled() { … }
void HangWatcher::InvalidateActiveExpectations() { … }
void HangWatcher::SetShuttingDown() { … }
HangWatcher::HangWatcher()
: … { … }
void HangWatcher::CreateHangWatcherInstance() { … }
#if !BUILDFLAG(IS_NACL)
debug::ScopedCrashKeyString
HangWatcher::GetTimeSinceLastCriticalMemoryPressureCrashKey() { … }
#endif
std::string HangWatcher::GetTimeSinceLastSystemPowerResumeCrashKeyValue()
const { … }
void HangWatcher::OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { … }
HangWatcher::~HangWatcher() { … }
void HangWatcher::Start() { … }
void HangWatcher::Stop() { … }
bool HangWatcher::IsWatchListEmpty() { … }
void HangWatcher::Wait() { … }
void HangWatcher::Run() { … }
HangWatcher* HangWatcher::GetInstance() { … }
void HangWatcher::RecordHang() { … }
ScopedClosureRunner HangWatcher::RegisterThreadInternal(
ThreadType thread_type) { … }
ScopedClosureRunner HangWatcher::RegisterThread(ThreadType thread_type) { … }
base::TimeTicks HangWatcher::WatchStateSnapShot::GetHighestDeadline() const { … }
HangWatcher::WatchStateSnapShot::WatchStateSnapShot() = default;
void HangWatcher::WatchStateSnapShot::Init(
const HangWatchStates& watch_states,
base::TimeTicks deadline_ignore_threshold,
base::TimeDelta monitoring_period) { … }
void HangWatcher::WatchStateSnapShot::Clear() { … }
HangWatcher::WatchStateSnapShot::WatchStateSnapShot(
const WatchStateSnapShot& other) = default;
HangWatcher::WatchStateSnapShot::~WatchStateSnapShot() = default;
std::string HangWatcher::WatchStateSnapShot::PrepareHungThreadListCrashKey()
const { … }
bool HangWatcher::WatchStateSnapShot::IsActionable() const { … }
HangWatcher::WatchStateSnapShot HangWatcher::GrabWatchStateSnapshotForTesting()
const { … }
void HangWatcher::Monitor() { … }
void HangWatcher::DoDumpWithoutCrashing(
const WatchStateSnapShot& watch_state_snapshot) { … }
void HangWatcher::SetAfterMonitorClosureForTesting(
base::RepeatingClosure closure) { … }
void HangWatcher::SetOnHangClosureForTesting(base::RepeatingClosure closure) { … }
void HangWatcher::SetMonitoringPeriodForTesting(base::TimeDelta period) { … }
void HangWatcher::SetAfterWaitCallbackForTesting(
RepeatingCallback<void(TimeTicks)> callback) { … }
void HangWatcher::SignalMonitorEventForTesting() { … }
void HangWatcher::StopMonitoringForTesting() { … }
void HangWatcher::SetTickClockForTesting(const base::TickClock* tick_clock) { … }
void HangWatcher::BlockIfCaptureInProgress() { … }
void HangWatcher::UnregisterThread() { … }
namespace internal {
namespace {
constexpr uint64_t kOnlyDeadlineMask = …;
constexpr uint64_t kOnlyFlagsMask = …;
constexpr uint64_t kMaximumFlag = …;
constexpr uint64_t kPersistentFlagsAndDeadlineMask = …;
}
static_assert …;
static_assert …;
HangWatchDeadline::HangWatchDeadline() = default;
HangWatchDeadline::~HangWatchDeadline() = default;
std::pair<uint64_t, TimeTicks> HangWatchDeadline::GetFlagsAndDeadline() const { … }
TimeTicks HangWatchDeadline::GetDeadline() const { … }
TimeTicks HangWatchDeadline::Max() { … }
bool HangWatchDeadline::IsFlagSet(Flag flag, uint64_t flags) { … }
void HangWatchDeadline::SetDeadline(TimeTicks new_deadline) { … }
bool HangWatchDeadline::SetShouldBlockOnHang(uint64_t old_flags,
TimeTicks old_deadline) { … }
void HangWatchDeadline::SetIgnoreCurrentWatchHangsInScope() { … }
void HangWatchDeadline::UnsetIgnoreCurrentWatchHangsInScope() { … }
void HangWatchDeadline::SetPersistentFlag(Flag flag) { … }
void HangWatchDeadline::ClearPersistentFlag(Flag flag) { … }
uint64_t HangWatchDeadline::ExtractFlags(uint64_t bits) { … }
uint64_t HangWatchDeadline::ExtractDeadline(uint64_t bits) { … }
TimeTicks HangWatchDeadline::DeadlineFromBits(uint64_t bits) { … }
bool HangWatchDeadline::IsFlagSet(Flag flag) const { … }
void HangWatchDeadline::SetSwitchBitsClosureForTesting(
RepeatingCallback<uint64_t(void)> closure) { … }
void HangWatchDeadline::ResetSwitchBitsClosureForTesting() { … }
uint64_t HangWatchDeadline::SwitchBitsForTesting() { … }
HangWatchState::HangWatchState(HangWatcher::ThreadType thread_type)
: … { … }
HangWatchState::~HangWatchState() { … }
std::unique_ptr<HangWatchState>
HangWatchState::CreateHangWatchStateForCurrentThread(
HangWatcher::ThreadType thread_type) { … }
TimeTicks HangWatchState::GetDeadline() const { … }
std::pair<uint64_t, TimeTicks> HangWatchState::GetFlagsAndDeadline() const { … }
void HangWatchState::SetDeadline(TimeTicks deadline) { … }
bool HangWatchState::IsOverDeadline() const { … }
void HangWatchState::SetIgnoreCurrentWatchHangsInScope() { … }
void HangWatchState::UnsetIgnoreCurrentWatchHangsInScope() { … }
bool HangWatchState::SetShouldBlockOnHang(uint64_t old_flags,
TimeTicks old_deadline) { … }
bool HangWatchState::IsFlagSet(HangWatchDeadline::Flag flag) { … }
#if DCHECK_IS_ON()
void HangWatchState::SetCurrentWatchHangsInScope(
WatchHangsInScope* current_hang_watch_scope_enable) { … }
WatchHangsInScope* HangWatchState::GetCurrentWatchHangsInScope() { … }
#endif
HangWatchDeadline* HangWatchState::GetHangWatchDeadlineForTesting() { … }
void HangWatchState::IncrementNestingLevel() { … }
void HangWatchState::DecrementNestingLevel() { … }
HangWatchState* HangWatchState::GetHangWatchStateForCurrentThread() { … }
PlatformThreadId HangWatchState::GetThreadID() const { … }
}
}