| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 #include "components/metrics/leak_detector/leak_detector.h" | 5 #include "components/metrics/leak_detector/leak_detector.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| 11 #include "base/allocator/allocator_extension.h" | 11 #include "base/allocator/allocator_extension.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/location.h" |
| 14 #include "base/logging.h" | 15 #include "base/logging.h" |
| 15 #include "base/numerics/safe_conversions.h" | 16 #include "base/numerics/safe_conversions.h" |
| 16 #include "base/threading/thread_local.h" | 17 #include "base/threading/thread_local.h" |
| 17 #include "components/metrics/leak_detector/custom_allocator.h" | 18 #include "components/metrics/leak_detector/custom_allocator.h" |
| 18 #include "components/metrics/leak_detector/leak_detector_impl.h" | 19 #include "components/metrics/leak_detector/leak_detector_impl.h" |
| 19 #include "content/public/browser/browser_thread.h" | |
| 20 | 20 |
| 21 #if defined(OS_CHROMEOS) | 21 #if defined(OS_CHROMEOS) |
| 22 #include <link.h> // for dl_iterate_phdr | 22 #include <link.h> // for dl_iterate_phdr |
| 23 #else | 23 #else |
| 24 #error "Getting binary mapping info is not supported on this platform." | 24 #error "Getting binary mapping info is not supported on this platform." |
| 25 #endif // defined(OS_CHROMEOS) | 25 #endif // defined(OS_CHROMEOS) |
| 26 | 26 |
| 27 namespace metrics { | 27 namespace metrics { |
| 28 | 28 |
| 29 using InternalLeakReport = leak_detector::LeakDetectorImpl::LeakReport; | 29 using InternalLeakReport = leak_detector::LeakDetectorImpl::LeakReport; |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 g_hook_data_tls.Get().Set(reinterpret_cast<void*>(ptr_value)); | 153 g_hook_data_tls.Get().Set(reinterpret_cast<void*>(ptr_value)); |
| 154 } | 154 } |
| 155 | 155 |
| 156 } // namespace | 156 } // namespace |
| 157 | 157 |
| 158 // static | 158 // static |
| 159 LeakDetector* LeakDetector::GetInstance() { | 159 LeakDetector* LeakDetector::GetInstance() { |
| 160 return g_instance.Pointer(); | 160 return g_instance.Pointer(); |
| 161 } | 161 } |
| 162 | 162 |
| 163 void LeakDetector::Init(const MemoryLeakReportProto::Params& params) { | 163 void LeakDetector::Init(const MemoryLeakReportProto::Params& params, |
| 164 scoped_refptr<base::TaskRunner> task_runner) { |
| 164 DCHECK(thread_checker_.CalledOnValidThread()); | 165 DCHECK(thread_checker_.CalledOnValidThread()); |
| 165 DCHECK_GT(params.sampling_rate(), 0); | 166 DCHECK_GT(params.sampling_rate(), 0); |
| 166 | 167 |
| 167 sampling_factor_ = | 168 sampling_factor_ = |
| 168 base::saturated_cast<uint64_t>(params.sampling_rate() * UINT64_MAX); | 169 base::saturated_cast<uint64_t>(params.sampling_rate() * UINT64_MAX); |
| 169 | 170 |
| 170 analysis_interval_bytes_ = params.analysis_interval_bytes(); | 171 analysis_interval_bytes_ = params.analysis_interval_bytes(); |
| 171 max_call_stack_unwind_depth_ = params.max_stack_depth(); | 172 max_call_stack_unwind_depth_ = params.max_stack_depth(); |
| 172 | 173 |
| 173 MappingInfo mapping = {0}; | 174 MappingInfo mapping = {0}; |
| 174 #if defined(OS_CHROMEOS) | 175 #if defined(OS_CHROMEOS) |
| 175 // Locate the Chrome binary mapping info. | 176 // Locate the Chrome binary mapping info. |
| 176 dl_iterate_phdr(IterateLoadedObjects, &mapping); | 177 dl_iterate_phdr(IterateLoadedObjects, &mapping); |
| 177 #endif // defined(OS_CHROMEOS) | 178 #endif // defined(OS_CHROMEOS) |
| 178 | 179 |
| 180 task_runner_ = task_runner; |
| 181 |
| 179 // CustomAllocator can use the default allocator, as long as the hook | 182 // CustomAllocator can use the default allocator, as long as the hook |
| 180 // functions can handle recursive calls. | 183 // functions can handle recursive calls. |
| 181 leak_detector::CustomAllocator::Initialize(); | 184 leak_detector::CustomAllocator::Initialize(); |
| 182 | 185 |
| 183 // The initialization should be done only once. Check for this by examining | 186 // The initialization should be done only once. Check for this by examining |
| 184 // whether |impl_| has already been initialized. | 187 // whether |impl_| has already been initialized. |
| 185 CHECK(!impl_.get()) << "Cannot initialize LeakDetector more than once!"; | 188 CHECK(!impl_.get()) << "Cannot initialize LeakDetector more than once!"; |
| 186 impl_.reset(new leak_detector::LeakDetectorImpl( | 189 impl_.reset(new leak_detector::LeakDetectorImpl( |
| 187 mapping.addr, mapping.size, params.size_suspicion_threshold(), | 190 mapping.addr, mapping.size, params.size_suspicion_threshold(), |
| 188 params.call_stack_suspicion_threshold())); | 191 params.call_stack_suspicion_threshold())); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 | 316 |
| 314 inline bool LeakDetector::ShouldSample(const void* ptr) const { | 317 inline bool LeakDetector::ShouldSample(const void* ptr) const { |
| 315 return PointerToHash(ptr) < sampling_factor_; | 318 return PointerToHash(ptr) < sampling_factor_; |
| 316 } | 319 } |
| 317 | 320 |
| 318 void LeakDetector::NotifyObservers( | 321 void LeakDetector::NotifyObservers( |
| 319 const std::vector<MemoryLeakReportProto>& reports) { | 322 const std::vector<MemoryLeakReportProto>& reports) { |
| 320 if (reports.empty()) | 323 if (reports.empty()) |
| 321 return; | 324 return; |
| 322 | 325 |
| 323 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { | 326 if (!task_runner_->RunsTasksOnCurrentThread()) { |
| 324 content::BrowserThread::PostTask( | 327 task_runner_->PostTask(FROM_HERE, |
| 325 content::BrowserThread::UI, FROM_HERE, | 328 base::Bind(&LeakDetector::NotifyObservers, |
| 326 base::Bind(&LeakDetector::NotifyObservers, base::Unretained(this), | 329 base::Unretained(this), reports)); |
| 327 reports)); | |
| 328 return; | 330 return; |
| 329 } | 331 } |
| 330 | 332 |
| 331 { | 333 { |
| 332 base::AutoLock lock(observers_lock_); | 334 base::AutoLock lock(observers_lock_); |
| 333 FOR_EACH_OBSERVER(Observer, observers_, OnLeaksFound(reports)); | 335 FOR_EACH_OBSERVER(Observer, observers_, OnLeaksFound(reports)); |
| 334 } | 336 } |
| 335 } | 337 } |
| 336 | 338 |
| 337 } // namespace metrics | 339 } // namespace metrics |
| OLD | NEW |