123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- // Copyright 2013 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "base/debug/dump_without_crashing.h"
- #include "base/check.h"
- #include "base/metrics/histogram_functions.h"
- #include "base/no_destructor.h"
- #include "base/synchronization/lock.h"
- #include "base/trace_event/base_tracing.h"
- namespace {
- // Pointer to the function that's called by DumpWithoutCrashing* to dump the
- // process's memory.
- void(CDECL* dump_without_crashing_function_)() = nullptr;
- template <typename Map, typename Key>
- bool ShouldDump(Map& map, Key& key, base::TimeDelta time_between_dumps) {
- static base::NoDestructor<base::Lock> lock;
- base::AutoLock auto_lock(*lock);
- base::TimeTicks now = base::TimeTicks::Now();
- auto [it, inserted] = map.emplace(key, now);
- if (inserted) {
- return true;
- }
- if (now - it->second >= time_between_dumps) {
- it->second = now;
- return true;
- }
- return false;
- }
- // This function takes `location` and `time_between_dumps` as an input
- // and checks if DumpWithoutCrashing() meets the requirements to take the dump
- // or not.
- bool ShouldDumpWithoutCrashWithLocation(const base::Location& location,
- base::TimeDelta time_between_dumps) {
- static base::NoDestructor<std::map<base::Location, base::TimeTicks>>
- location_to_timestamp;
- return ShouldDump(*location_to_timestamp, location, time_between_dumps);
- }
- // Pair of `location` and `unique_identifier` creates a unique key and checks
- // if DumpWithoutCrashingWithUniqueId() meets the requirements to take dump or
- // not.
- bool ShouldDumpWithoutCrashWithLocationAndUniqueId(
- size_t unique_identifier,
- const base::Location& location,
- base::TimeDelta time_between_dumps) {
- static base::NoDestructor<
- std::map<std::pair<base::Location, size_t>, base::TimeTicks>>
- location_and_unique_identifier_to_timestamp;
- std::pair<base::Location, size_t> key(location, unique_identifier);
- return ShouldDump(*location_and_unique_identifier_to_timestamp, key,
- time_between_dumps);
- }
- } // namespace
- namespace base {
- namespace debug {
- bool DumpWithoutCrashingUnthrottled() {
- TRACE_EVENT0("base", "DumpWithoutCrashingUnthrottled");
- if (dump_without_crashing_function_) {
- (*dump_without_crashing_function_)();
- return true;
- }
- return false;
- }
- bool DumpWithoutCrashing(const base::Location& location,
- base::TimeDelta time_between_dumps) {
- TRACE_EVENT0("base", "DumpWithoutCrashing");
- if (dump_without_crashing_function_ &&
- ShouldDumpWithoutCrashWithLocation(location, time_between_dumps)) {
- (*dump_without_crashing_function_)();
- base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus",
- DumpWithoutCrashingStatus::kUploaded);
- return true;
- }
- base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus",
- DumpWithoutCrashingStatus::kThrottled);
- return false;
- }
- bool DumpWithoutCrashingWithUniqueId(size_t unique_identifier,
- const base::Location& location,
- base::TimeDelta time_between_dumps) {
- TRACE_EVENT0("base", "DumpWithoutCrashingWithUniqueId");
- if (dump_without_crashing_function_ &&
- ShouldDumpWithoutCrashWithLocationAndUniqueId(unique_identifier, location,
- time_between_dumps)) {
- (*dump_without_crashing_function_)();
- base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus",
- DumpWithoutCrashingStatus::kUploaded);
- return true;
- }
- base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus",
- DumpWithoutCrashingStatus::kThrottled);
- return false;
- }
- void SetDumpWithoutCrashingFunction(void (CDECL *function)()) {
- #if !defined(COMPONENT_BUILD)
- // In component builds, the same base is shared between modules
- // so might be initialized several times. However in non-
- // component builds this should never happen.
- DCHECK(!dump_without_crashing_function_ || !function);
- #endif
- dump_without_crashing_function_ = function;
- }
- } // namespace debug
- } // namespace base
|