File: leak_detector.h

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (161 lines) | stat: -rw-r--r-- 5,622 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2016 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.

#ifndef COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_
#define COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_

#include <stddef.h>
#include <stdint.h>

#include <list>
#include <memory>
#include <vector>

#include "base/feature_list.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
#include "base/threading/thread_checker.h"

namespace base {
template <typename T>
struct DefaultLazyInstanceTraits;
}

namespace metrics {

class MemoryLeakReportProto;
class MemoryLeakReportProto_Params;

namespace leak_detector {
class LeakDetectorImpl;
}

// LeakDetector is an interface layer that connects the allocator
// (base::allocator), the leak detector logic (LeakDetectorImpl), and any
// external classes interested in receiving leak reports (extend the Observer
// class).
//
// Only one instance of this class can exist. Access this instance using
// GetInstance(). Do not create an instance of this class directly.
//
// These member functions are thread-safe:
// - AllocHook
// - FreeHook
// - AddObserver
// - RemoveObserver
//
// All other functions must always be called from the same thread. This is
// enforced with a DCHECK.
class LeakDetector {
 public:
  // Interface for receiving leak reports.
  class Observer {
   public:
    virtual ~Observer() {}

    // Called by leak detector to report leaks.
    virtual void OnLeaksFound(
        const std::vector<MemoryLeakReportProto>& reports) = 0;
  };

  // Returns the sole instance, or creates it if it hasn't already been created.
  static LeakDetector* GetInstance();

  // Initializes leak detector. Args:
  // - |params| is a set of parameters used by the leak detector. See definition
  //   of MemoryLeakReportProto_Params for info about individual parameters.
  // - |task_runner| is a TaskRunner to which NotifyObservers() should be
  //   posted, if it is initally called from a different thread than the one on
  //   which |task_runner| runs.
  void Init(const MemoryLeakReportProto_Params& params,
            scoped_refptr<base::TaskRunner> task_runner);

  // Initializes the thread-local storage slot to be used by LeakDetector.
  static void InitTLSSlot();

  // Add |observer| to the list of stored Observers, i.e. |observers_|, to which
  // the leak detector will report leaks.
  void AddObserver(Observer* observer);

  // Remove |observer| from |observers_|.
  void RemoveObserver(Observer* observer);

 private:
  friend base::DefaultLazyInstanceTraits<LeakDetector>;
  FRIEND_TEST_ALL_PREFIXES(LeakDetectorTest, NotifyObservers);

  // Keep these private, as this class is meant to be initialized only through
  // the lazy instance, and never destroyed.
  LeakDetector();
  ~LeakDetector();

  // Allocator hook function that processes each alloc. Performs sampling and
  // unwinds call stack if necessary. Passes the allocated memory |ptr| and
  // allocation size |size| along with call stack info to RecordAlloc().
  static void AllocHook(const void* ptr, size_t size);

  // Allocator hook function that processes each free. Performs sampling and
  // passes the allocation address |ptr| to |impl_|.
  static void FreeHook(const void* ptr);

  // Give an pointer |ptr|, computes a hash of the pointer value and compares it
  // against |sampling_factor_| to determine if it should be sampled. This
  // allows the same pointer to be sampled during both alloc and free.
  bool ShouldSample(const void* ptr) const;

  // Notifies all Observers in |observers_| with the given vector of leak
  // report protobufs. If it is not currently on the thread that corresponds to
  // |task_runner_|, it will post the call as task to |task_runner_|.
  void NotifyObservers(const std::vector<MemoryLeakReportProto>& reports);

  // List of observers to notify when there's a leak report.
  // TODO(sque): Consider using ObserverListThreadSafe instead.
  base::ObserverList<Observer> observers_;

  // For atomic access to |observers_|.
  base::Lock observers_lock_;

  // Handles leak detection logic. Must be called under lock as LeakDetectorImpl
  // uses shared resources.
  std::unique_ptr<leak_detector::LeakDetectorImpl> impl_;

  // For thread safety.
  base::ThreadChecker thread_checker_;

  // For posting leak report notifications.
  scoped_refptr<base::TaskRunner> task_runner_;

  // Total number of bytes allocated, computed before sampling.
  size_t total_alloc_size_;

  // The value of |total_alloc_size_| the last time there was a leak analysis,
  // rounded down to the nearest multiple of |analysis_interval_bytes_|.
  size_t last_analysis_alloc_size_;

  // For atomic access to |impl_|, |total_alloc_size_| and
  // |last_analysis_alloc_size_|.
  base::Lock recording_lock_;

  // Perform a leak analysis each time this many bytes have been allocated since
  // the previous analysis.
  size_t analysis_interval_bytes_;

  // When unwinding call stacks, unwind no more than this number of frames.
  size_t max_call_stack_unwind_depth_;

  // Sampling factor used by ShouldSample(). It's full range of values
  // corresponds to the allowable range of |sampling_rate| passed in during
  // initialization: [0.0f, 1.0f] -> [0, UINT64_MAX].
  uint64_t sampling_factor_;

  DISALLOW_COPY_AND_ASSIGN(LeakDetector);
};

}  // namespace metrics

#endif  // COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_