xref: /aosp_15_r20/external/cronet/base/debug/dump_without_crashing.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/debug/dump_without_crashing.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/no_destructor.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker namespace {
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker // Pointer to the function that's called by DumpWithoutCrashing* to dump the
16*6777b538SAndroid Build Coastguard Worker // process's memory.
17*6777b538SAndroid Build Coastguard Worker void(CDECL* dump_without_crashing_function_)() = nullptr;
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker template <typename Map, typename Key>
ShouldDump(Map & map,Key & key,base::TimeDelta time_between_dumps)20*6777b538SAndroid Build Coastguard Worker bool ShouldDump(Map& map, Key& key, base::TimeDelta time_between_dumps) {
21*6777b538SAndroid Build Coastguard Worker   static base::NoDestructor<base::Lock> lock;
22*6777b538SAndroid Build Coastguard Worker   base::AutoLock auto_lock(*lock);
23*6777b538SAndroid Build Coastguard Worker   base::TimeTicks now = base::TimeTicks::Now();
24*6777b538SAndroid Build Coastguard Worker   auto [it, inserted] = map.emplace(key, now);
25*6777b538SAndroid Build Coastguard Worker   if (inserted) {
26*6777b538SAndroid Build Coastguard Worker     return true;
27*6777b538SAndroid Build Coastguard Worker   }
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker   if (now - it->second >= time_between_dumps) {
30*6777b538SAndroid Build Coastguard Worker     it->second = now;
31*6777b538SAndroid Build Coastguard Worker     return true;
32*6777b538SAndroid Build Coastguard Worker   }
33*6777b538SAndroid Build Coastguard Worker   return false;
34*6777b538SAndroid Build Coastguard Worker }
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker // Map used to store the most recent time a location called
37*6777b538SAndroid Build Coastguard Worker // ShouldDumpWithoutCrashWithLocation.
LocationToTimestampMap()38*6777b538SAndroid Build Coastguard Worker std::map<base::Location, base::TimeTicks>& LocationToTimestampMap() {
39*6777b538SAndroid Build Coastguard Worker   static base::NoDestructor<std::map<base::Location, base::TimeTicks>>
40*6777b538SAndroid Build Coastguard Worker       location_to_timestamp;
41*6777b538SAndroid Build Coastguard Worker   return *location_to_timestamp;
42*6777b538SAndroid Build Coastguard Worker }
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker // Map used to store the most recent time a pair of location and
45*6777b538SAndroid Build Coastguard Worker // unique_identifier called ShouldDumpWithoutCrashWithLocationAndUniqueId.
46*6777b538SAndroid Build Coastguard Worker std::map<std::pair<base::Location, size_t>, base::TimeTicks>&
LocationAndUniqueIdentifierToTimestampMap()47*6777b538SAndroid Build Coastguard Worker LocationAndUniqueIdentifierToTimestampMap() {
48*6777b538SAndroid Build Coastguard Worker   static base::NoDestructor<
49*6777b538SAndroid Build Coastguard Worker       std::map<std::pair<base::Location, size_t>, base::TimeTicks>>
50*6777b538SAndroid Build Coastguard Worker       location_and_unique_identifier_to_timestamp;
51*6777b538SAndroid Build Coastguard Worker   return *location_and_unique_identifier_to_timestamp;
52*6777b538SAndroid Build Coastguard Worker }
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker // This function takes `location` and `time_between_dumps` as an input
55*6777b538SAndroid Build Coastguard Worker // and checks if DumpWithoutCrashing() meets the requirements to take the dump
56*6777b538SAndroid Build Coastguard Worker // or not.
ShouldDumpWithoutCrashWithLocation(const base::Location & location,base::TimeDelta time_between_dumps)57*6777b538SAndroid Build Coastguard Worker bool ShouldDumpWithoutCrashWithLocation(const base::Location& location,
58*6777b538SAndroid Build Coastguard Worker                                         base::TimeDelta time_between_dumps) {
59*6777b538SAndroid Build Coastguard Worker   return ShouldDump(LocationToTimestampMap(), location, time_between_dumps);
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker // Pair of `location` and `unique_identifier` creates a unique key and checks
63*6777b538SAndroid Build Coastguard Worker // if DumpWithoutCrashingWithUniqueId() meets the requirements to take dump or
64*6777b538SAndroid Build Coastguard Worker // not.
ShouldDumpWithoutCrashWithLocationAndUniqueId(size_t unique_identifier,const base::Location & location,base::TimeDelta time_between_dumps)65*6777b538SAndroid Build Coastguard Worker bool ShouldDumpWithoutCrashWithLocationAndUniqueId(
66*6777b538SAndroid Build Coastguard Worker     size_t unique_identifier,
67*6777b538SAndroid Build Coastguard Worker     const base::Location& location,
68*6777b538SAndroid Build Coastguard Worker     base::TimeDelta time_between_dumps) {
69*6777b538SAndroid Build Coastguard Worker   std::pair<base::Location, size_t> key(location, unique_identifier);
70*6777b538SAndroid Build Coastguard Worker   return ShouldDump(LocationAndUniqueIdentifierToTimestampMap(), key,
71*6777b538SAndroid Build Coastguard Worker                     time_between_dumps);
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker }  // namespace
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker namespace base {
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker namespace debug {
79*6777b538SAndroid Build Coastguard Worker 
DumpWithoutCrashingUnthrottled()80*6777b538SAndroid Build Coastguard Worker bool DumpWithoutCrashingUnthrottled() {
81*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "DumpWithoutCrashingUnthrottled");
82*6777b538SAndroid Build Coastguard Worker   if (dump_without_crashing_function_) {
83*6777b538SAndroid Build Coastguard Worker     (*dump_without_crashing_function_)();
84*6777b538SAndroid Build Coastguard Worker     return true;
85*6777b538SAndroid Build Coastguard Worker   }
86*6777b538SAndroid Build Coastguard Worker   return false;
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker 
DumpWithoutCrashing(const base::Location & location,base::TimeDelta time_between_dumps)89*6777b538SAndroid Build Coastguard Worker bool DumpWithoutCrashing(const base::Location& location,
90*6777b538SAndroid Build Coastguard Worker                          base::TimeDelta time_between_dumps) {
91*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "DumpWithoutCrashing");
92*6777b538SAndroid Build Coastguard Worker   if (dump_without_crashing_function_ &&
93*6777b538SAndroid Build Coastguard Worker       ShouldDumpWithoutCrashWithLocation(location, time_between_dumps)) {
94*6777b538SAndroid Build Coastguard Worker     (*dump_without_crashing_function_)();
95*6777b538SAndroid Build Coastguard Worker     base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus",
96*6777b538SAndroid Build Coastguard Worker                                   DumpWithoutCrashingStatus::kUploaded);
97*6777b538SAndroid Build Coastguard Worker     return true;
98*6777b538SAndroid Build Coastguard Worker   }
99*6777b538SAndroid Build Coastguard Worker   base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus",
100*6777b538SAndroid Build Coastguard Worker                                 DumpWithoutCrashingStatus::kThrottled);
101*6777b538SAndroid Build Coastguard Worker   return false;
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker 
DumpWithoutCrashingWithUniqueId(size_t unique_identifier,const base::Location & location,base::TimeDelta time_between_dumps)104*6777b538SAndroid Build Coastguard Worker bool DumpWithoutCrashingWithUniqueId(size_t unique_identifier,
105*6777b538SAndroid Build Coastguard Worker                                      const base::Location& location,
106*6777b538SAndroid Build Coastguard Worker                                      base::TimeDelta time_between_dumps) {
107*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "DumpWithoutCrashingWithUniqueId");
108*6777b538SAndroid Build Coastguard Worker   if (dump_without_crashing_function_ &&
109*6777b538SAndroid Build Coastguard Worker       ShouldDumpWithoutCrashWithLocationAndUniqueId(unique_identifier, location,
110*6777b538SAndroid Build Coastguard Worker                                                     time_between_dumps)) {
111*6777b538SAndroid Build Coastguard Worker     (*dump_without_crashing_function_)();
112*6777b538SAndroid Build Coastguard Worker     base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus",
113*6777b538SAndroid Build Coastguard Worker                                   DumpWithoutCrashingStatus::kUploaded);
114*6777b538SAndroid Build Coastguard Worker     return true;
115*6777b538SAndroid Build Coastguard Worker   }
116*6777b538SAndroid Build Coastguard Worker   base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus",
117*6777b538SAndroid Build Coastguard Worker                                 DumpWithoutCrashingStatus::kThrottled);
118*6777b538SAndroid Build Coastguard Worker   return false;
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker 
SetDumpWithoutCrashingFunction(void (CDECL * function)())121*6777b538SAndroid Build Coastguard Worker void SetDumpWithoutCrashingFunction(void (CDECL *function)()) {
122*6777b538SAndroid Build Coastguard Worker #if !defined(COMPONENT_BUILD)
123*6777b538SAndroid Build Coastguard Worker   // In component builds, the same base is shared between modules
124*6777b538SAndroid Build Coastguard Worker   // so might be initialized several times. However in non-
125*6777b538SAndroid Build Coastguard Worker   // component builds this should never happen.
126*6777b538SAndroid Build Coastguard Worker   DCHECK(!dump_without_crashing_function_ || !function);
127*6777b538SAndroid Build Coastguard Worker #endif
128*6777b538SAndroid Build Coastguard Worker   dump_without_crashing_function_ = function;
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker 
ClearMapsForTesting()131*6777b538SAndroid Build Coastguard Worker void ClearMapsForTesting() {
132*6777b538SAndroid Build Coastguard Worker   LocationToTimestampMap().clear();
133*6777b538SAndroid Build Coastguard Worker   LocationAndUniqueIdentifierToTimestampMap().clear();
134*6777b538SAndroid Build Coastguard Worker }
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker }  // namespace debug
137*6777b538SAndroid Build Coastguard Worker }  // namespace base
138