dump_without_crashing.cc 4.2 KB

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