OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ | 5 #ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ |
6 #define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ | 6 #define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ |
7 | 7 |
8 #include <vector> | 8 #include <set> |
9 | 9 |
10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
11 #include "base/containers/hash_tables.h" | 11 #include "base/containers/hash_tables.h" |
12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
13 #include "base/memory/singleton.h" | 13 #include "base/memory/singleton.h" |
14 #include "base/synchronization/lock.h" | 14 #include "base/synchronization/lock.h" |
15 #include "base/timer/timer.h" | 15 #include "base/timer/timer.h" |
16 #include "base/trace_event/memory_dump_request_args.h" | 16 #include "base/trace_event/memory_dump_request_args.h" |
| 17 #include "base/trace_event/process_memory_dump.h" |
17 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
18 | 19 |
19 namespace base { | 20 namespace base { |
20 | 21 |
21 class SingleThreadTaskRunner; | 22 class SingleThreadTaskRunner; |
22 | 23 |
23 namespace trace_event { | 24 namespace trace_event { |
24 | 25 |
25 namespace { | |
26 class ProcessMemoryDumpHolder; | |
27 } | |
28 | |
29 class MemoryDumpManagerDelegate; | 26 class MemoryDumpManagerDelegate; |
30 class MemoryDumpProvider; | 27 class MemoryDumpProvider; |
31 class ProcessMemoryDump; | |
32 class MemoryDumpSessionState; | 28 class MemoryDumpSessionState; |
33 | 29 |
34 // This is the interface exposed to the rest of the codebase to deal with | 30 // This is the interface exposed to the rest of the codebase to deal with |
35 // memory tracing. The main entry point for clients is represented by | 31 // memory tracing. The main entry point for clients is represented by |
36 // RequestDumpPoint(). The extension by Un(RegisterDumpProvider). | 32 // RequestDumpPoint(). The extension by Un(RegisterDumpProvider). |
37 class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver { | 33 class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver { |
38 public: | 34 public: |
| 35 static const uint64 kInvalidTracingProcessId; |
39 static const char* const kTraceCategoryForTesting; | 36 static const char* const kTraceCategoryForTesting; |
40 | 37 |
41 static MemoryDumpManager* GetInstance(); | 38 static MemoryDumpManager* GetInstance(); |
42 | 39 |
43 // Invoked once per process to register the TraceLog observer. | 40 // Invoked once per process to register the TraceLog observer. |
44 void Initialize(); | 41 void Initialize(); |
45 | 42 |
46 // See the lifetime and thread-safety requirements on the delegate below in | 43 // See the lifetime and thread-safety requirements on the delegate below in |
47 // the |MemoryDumpManagerDelegate| docstring. | 44 // the |MemoryDumpManagerDelegate| docstring. |
48 void SetDelegate(MemoryDumpManagerDelegate* delegate); | 45 void SetDelegate(MemoryDumpManagerDelegate* delegate); |
(...skipping 25 matching lines...) Expand all Loading... |
74 void OnTraceLogEnabled() override; | 71 void OnTraceLogEnabled() override; |
75 void OnTraceLogDisabled() override; | 72 void OnTraceLogDisabled() override; |
76 | 73 |
77 // Returns the MemoryDumpSessionState object, which is shared by all the | 74 // Returns the MemoryDumpSessionState object, which is shared by all the |
78 // ProcessMemoryDump and MemoryAllocatorDump instances through all the tracing | 75 // ProcessMemoryDump and MemoryAllocatorDump instances through all the tracing |
79 // session lifetime. | 76 // session lifetime. |
80 const scoped_refptr<MemoryDumpSessionState>& session_state() const { | 77 const scoped_refptr<MemoryDumpSessionState>& session_state() const { |
81 return session_state_; | 78 return session_state_; |
82 } | 79 } |
83 | 80 |
| 81 // Derives a tracing process id from a child process id. Child process ids |
| 82 // cannot be used directly in tracing for security reasons (see: discussion in |
| 83 // crrev.com/1173263004). This method is meant to be used when dumping |
| 84 // cross-process shared memory from a process which knows the child process id |
| 85 // of its endpoints. The value returned by this method is guaranteed to be |
| 86 // equal to the value returned by tracing_process_id() in the corresponding |
| 87 // child process. |
| 88 // This will never return kInvalidTracingProcessId. |
| 89 static uint64 ChildProcessIdToTracingProcessId(int child_id); |
| 90 |
| 91 // Returns a unique id for the current process. The id can be retrieved only |
| 92 // by child processes and only when tracing is enabled. This is intended to |
| 93 // express cross-process sharing of memory dumps on the child-process side, |
| 94 // without having to know its own child process id. |
| 95 uint64 tracing_process_id() const { return tracing_process_id_; } |
| 96 |
84 private: | 97 private: |
85 // Descriptor struct used to hold information about registered MDPs. It is | |
86 // deliberately copyable, in order to allow to be used as hash_map value. | |
87 struct MemoryDumpProviderInfo { | |
88 MemoryDumpProviderInfo( | |
89 const scoped_refptr<SingleThreadTaskRunner>& task_runner); | |
90 ~MemoryDumpProviderInfo(); | |
91 | |
92 scoped_refptr<SingleThreadTaskRunner> task_runner; // Optional. | |
93 bool disabled; // For fail-safe logic (auto-disable failing MDPs). | |
94 }; | |
95 | |
96 friend struct DefaultDeleter<MemoryDumpManager>; // For the testing instance. | 98 friend struct DefaultDeleter<MemoryDumpManager>; // For the testing instance. |
97 friend struct DefaultSingletonTraits<MemoryDumpManager>; | 99 friend struct DefaultSingletonTraits<MemoryDumpManager>; |
98 friend class MemoryDumpManagerDelegate; | 100 friend class MemoryDumpManagerDelegate; |
99 friend class MemoryDumpManagerTest; | 101 friend class MemoryDumpManagerTest; |
| 102 FRIEND_TEST_ALL_PREFIXES(MemoryDumpManagerTest, DisableFailingDumpers); |
| 103 |
| 104 // Descriptor struct used to hold information about registered MDPs. It is |
| 105 // deliberately copyable, in order to allow it to be used as std::set value. |
| 106 struct MemoryDumpProviderInfo { |
| 107 MemoryDumpProviderInfo( |
| 108 MemoryDumpProvider* dump_provider, |
| 109 const scoped_refptr<SingleThreadTaskRunner>& task_runner); |
| 110 ~MemoryDumpProviderInfo(); |
| 111 |
| 112 // Define a total order based on the thread (i.e. |task_runner|) affinity, |
| 113 // so that all MDP belonging to the same thread are adjacent in the set. |
| 114 bool operator<(const MemoryDumpProviderInfo& other) const; |
| 115 |
| 116 MemoryDumpProvider* const dump_provider; |
| 117 scoped_refptr<SingleThreadTaskRunner> task_runner; // Optional. |
| 118 |
| 119 // For fail-safe logic (auto-disable failing MDPs). These fields are mutable |
| 120 // as can be safely changed without impacting the order within the set. |
| 121 mutable int consecutive_failures; |
| 122 mutable bool disabled; |
| 123 }; |
| 124 |
| 125 using MemoryDumpProviderInfoSet = std::set<MemoryDumpProviderInfo>; |
| 126 |
| 127 // Holds the state of a process memory dump that needs to be carried over |
| 128 // across threads in order to fulfil an asynchronous CreateProcessDump() |
| 129 // request. At any time exactly one thread owns a ProcessMemoryDumpAsyncState. |
| 130 struct ProcessMemoryDumpAsyncState { |
| 131 ProcessMemoryDumpAsyncState( |
| 132 MemoryDumpRequestArgs req_args, |
| 133 MemoryDumpProviderInfoSet::iterator next_dump_provider, |
| 134 const scoped_refptr<MemoryDumpSessionState>& session_state, |
| 135 MemoryDumpCallback callback); |
| 136 ~ProcessMemoryDumpAsyncState(); |
| 137 |
| 138 // The ProcessMemoryDump container, where each dump provider will dump its |
| 139 // own MemoryAllocatorDump(s) upon the OnMemoryDump() call. |
| 140 ProcessMemoryDump process_memory_dump; |
| 141 |
| 142 // The arguments passed to the initial CreateProcessDump() request. |
| 143 const MemoryDumpRequestArgs req_args; |
| 144 |
| 145 // The |dump_providers_| iterator to the next dump provider that should be |
| 146 // invoked (or dump_providers_.end() if at the end of the sequence). |
| 147 MemoryDumpProviderInfoSet::iterator next_dump_provider; |
| 148 |
| 149 // Callback passed to the initial call to CreateProcessDump(). |
| 150 MemoryDumpCallback callback; |
| 151 |
| 152 // The thread on which FinalizeDumpAndAddToTrace() (and hence |callback|) |
| 153 // should be invoked. This is the thread on which the initial |
| 154 // CreateProcessDump() request was called. |
| 155 const scoped_refptr<SingleThreadTaskRunner> task_runner; |
| 156 |
| 157 private: |
| 158 DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpAsyncState); |
| 159 }; |
| 160 |
| 161 static const int kMaxConsecutiveFailuresCount; |
| 162 |
| 163 MemoryDumpManager(); |
| 164 ~MemoryDumpManager() override; |
100 | 165 |
101 static void SetInstanceForTesting(MemoryDumpManager* instance); | 166 static void SetInstanceForTesting(MemoryDumpManager* instance); |
102 | 167 static void FinalizeDumpAndAddToTrace( |
103 MemoryDumpManager(); | 168 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state); |
104 virtual ~MemoryDumpManager(); | 169 static void AbortDumpLocked(MemoryDumpCallback callback, |
| 170 scoped_refptr<SingleThreadTaskRunner> task_runner, |
| 171 uint64 dump_guid); |
105 | 172 |
106 // Internal, used only by MemoryDumpManagerDelegate. | 173 // Internal, used only by MemoryDumpManagerDelegate. |
107 // Creates a memory dump for the current process and appends it to the trace. | 174 // Creates a memory dump for the current process and appends it to the trace. |
108 // |callback| will be invoked asynchronously upon completion on the same | 175 // |callback| will be invoked asynchronously upon completion on the same |
109 // thread on which CreateProcessDump() was called. | 176 // thread on which CreateProcessDump() was called. |
110 void CreateProcessDump(const MemoryDumpRequestArgs& args, | 177 void CreateProcessDump(const MemoryDumpRequestArgs& args, |
111 const MemoryDumpCallback& callback); | 178 const MemoryDumpCallback& callback); |
112 | 179 |
113 bool InvokeDumpProviderLocked(MemoryDumpProvider* mdp, | 180 // Continues the ProcessMemoryDump started by CreateProcessDump(), hopping |
114 ProcessMemoryDump* pmd); | 181 // across threads as needed as specified by MDPs in RegisterDumpProvider(). |
115 void ContinueAsyncProcessDump( | 182 void ContinueAsyncProcessDump( |
116 MemoryDumpProvider* mdp, | 183 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state); |
117 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder); | |
118 | 184 |
119 hash_map<MemoryDumpProvider*, MemoryDumpProviderInfo> dump_providers_; | 185 // Pass kInvalidTracingProcessId to invalidate the id. |
| 186 void set_tracing_process_id(uint64 id) { |
| 187 DCHECK(tracing_process_id_ == kInvalidTracingProcessId || |
| 188 id == kInvalidTracingProcessId || tracing_process_id_ == id); |
| 189 tracing_process_id_ = id; |
| 190 } |
| 191 |
| 192 // An ordererd set of registered MemoryDumpProviderInfo(s), sorted by thread |
| 193 // affinity (MDPs belonging to the same thread are adjacent). |
| 194 MemoryDumpProviderInfoSet dump_providers_; |
| 195 |
| 196 // Flag used to signal that some provider was removed from |dump_providers_| |
| 197 // and therefore the current memory dump (if any) should be aborted. |
| 198 bool did_unregister_dump_provider_; |
120 | 199 |
121 // Shared among all the PMDs to keep state scoped to the tracing session. | 200 // Shared among all the PMDs to keep state scoped to the tracing session. |
122 scoped_refptr<MemoryDumpSessionState> session_state_; | 201 scoped_refptr<MemoryDumpSessionState> session_state_; |
123 | 202 |
124 MemoryDumpManagerDelegate* delegate_; // Not owned. | 203 MemoryDumpManagerDelegate* delegate_; // Not owned. |
125 | 204 |
126 // Protects from concurrent accesses to the |dump_providers_*| and |delegate_| | 205 // Protects from concurrent accesses to the |dump_providers_*| and |delegate_| |
127 // to guard against disabling logging while dumping on another thread. | 206 // to guard against disabling logging while dumping on another thread. |
128 Lock lock_; | 207 Lock lock_; |
129 | 208 |
130 // Optimization to avoid attempting any memory dump (i.e. to not walk an empty | 209 // Optimization to avoid attempting any memory dump (i.e. to not walk an empty |
131 // dump_providers_enabled_ list) when tracing is not enabled. | 210 // dump_providers_enabled_ list) when tracing is not enabled. |
132 subtle::AtomicWord memory_tracing_enabled_; | 211 subtle::AtomicWord memory_tracing_enabled_; |
133 | 212 |
134 // For time-triggered periodic dumps. | 213 // For time-triggered periodic dumps. |
135 RepeatingTimer<MemoryDumpManager> periodic_dump_timer_; | 214 RepeatingTimer<MemoryDumpManager> periodic_dump_timer_; |
136 | 215 |
| 216 // The unique id of the child process. This is created only for tracing and is |
| 217 // expected to be valid only when tracing is enabled. |
| 218 uint64 tracing_process_id_; |
| 219 |
137 // Skips the auto-registration of the core dumpers during Initialize(). | 220 // Skips the auto-registration of the core dumpers during Initialize(). |
138 bool skip_core_dumpers_auto_registration_for_testing_; | 221 bool skip_core_dumpers_auto_registration_for_testing_; |
139 | 222 |
140 DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager); | 223 DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager); |
141 }; | 224 }; |
142 | 225 |
143 // The delegate is supposed to be long lived (read: a Singleton) and thread | 226 // The delegate is supposed to be long lived (read: a Singleton) and thread |
144 // safe (i.e. should expect calls from any thread and handle thread hopping). | 227 // safe (i.e. should expect calls from any thread and handle thread hopping). |
145 class BASE_EXPORT MemoryDumpManagerDelegate { | 228 class BASE_EXPORT MemoryDumpManagerDelegate { |
146 public: | 229 public: |
147 virtual void RequestGlobalMemoryDump(const MemoryDumpRequestArgs& args, | 230 virtual void RequestGlobalMemoryDump(const MemoryDumpRequestArgs& args, |
148 const MemoryDumpCallback& callback) = 0; | 231 const MemoryDumpCallback& callback) = 0; |
149 | 232 |
150 // Determines whether the MemoryDumpManager instance should be the master | 233 // Determines whether the MemoryDumpManager instance should be the master |
151 // (the ones which initiates and coordinates the multiprocess dumps) or not. | 234 // (the ones which initiates and coordinates the multiprocess dumps) or not. |
152 virtual bool IsCoordinatorProcess() const = 0; | 235 virtual bool IsCoordinatorProcess() const = 0; |
153 | 236 |
154 protected: | 237 protected: |
155 MemoryDumpManagerDelegate() {} | 238 MemoryDumpManagerDelegate() {} |
156 virtual ~MemoryDumpManagerDelegate() {} | 239 virtual ~MemoryDumpManagerDelegate() {} |
157 | 240 |
158 void CreateProcessDump(const MemoryDumpRequestArgs& args, | 241 void CreateProcessDump(const MemoryDumpRequestArgs& args, |
159 const MemoryDumpCallback& callback) { | 242 const MemoryDumpCallback& callback) { |
160 MemoryDumpManager::GetInstance()->CreateProcessDump(args, callback); | 243 MemoryDumpManager::GetInstance()->CreateProcessDump(args, callback); |
161 } | 244 } |
162 | 245 |
| 246 void set_tracing_process_id(uint64 id) { |
| 247 MemoryDumpManager::GetInstance()->set_tracing_process_id(id); |
| 248 } |
| 249 |
163 private: | 250 private: |
164 DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerDelegate); | 251 DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerDelegate); |
165 }; | 252 }; |
166 | 253 |
167 } // namespace trace_event | 254 } // namespace trace_event |
168 } // namespace base | 255 } // namespace base |
169 | 256 |
170 #endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ | 257 #endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ |
OLD | NEW |