Chromium Code Reviews| 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 #include "components/tracing/common/process_metrics_memory_dump_provider.h" | 5 #include "components/tracing/common/process_metrics_memory_dump_provider.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 #include <mach/shared_region.h> | 31 #include <mach/shared_region.h> |
| 32 #include <sys/param.h> | 32 #include <sys/param.h> |
| 33 | 33 |
| 34 #include <mach-o/dyld_images.h> | 34 #include <mach-o/dyld_images.h> |
| 35 #include <mach-o/loader.h> | 35 #include <mach-o/loader.h> |
| 36 #include <mach/mach.h> | 36 #include <mach/mach.h> |
| 37 | 37 |
| 38 #include "base/numerics/safe_math.h" | 38 #include "base/numerics/safe_math.h" |
| 39 #endif // defined(OS_MACOSX) | 39 #endif // defined(OS_MACOSX) |
| 40 | 40 |
| 41 #if defined(OS_WIN) | |
| 42 #include <psapi.h> | |
| 43 #include <tchar.h> | |
| 44 #include <windows.h> | |
| 45 | |
| 46 #include <base/strings/sys_string_conversions.h> | |
| 47 #endif | |
| 48 | |
| 41 namespace tracing { | 49 namespace tracing { |
| 42 | 50 |
| 43 namespace { | 51 namespace { |
| 44 | 52 |
| 45 base::LazyInstance< | 53 base::LazyInstance< |
| 46 std::map<base::ProcessId, | 54 std::map<base::ProcessId, |
| 47 std::unique_ptr<ProcessMetricsMemoryDumpProvider>>>::Leaky | 55 std::unique_ptr<ProcessMetricsMemoryDumpProvider>>>::Leaky |
| 48 g_dump_providers_map = LAZY_INSTANCE_INITIALIZER; | 56 g_dump_providers_map = LAZY_INSTANCE_INITIALIZER; |
| 49 | 57 |
| 50 #if defined(OS_LINUX) || defined(OS_ANDROID) | 58 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 base::ScopedFILE smaps_file(fopen(file_name.c_str(), "r")); | 234 base::ScopedFILE smaps_file(fopen(file_name.c_str(), "r")); |
| 227 res = ReadLinuxProcSmapsFile(smaps_file.get(), pmd->process_mmaps()); | 235 res = ReadLinuxProcSmapsFile(smaps_file.get(), pmd->process_mmaps()); |
| 228 } | 236 } |
| 229 | 237 |
| 230 if (res) | 238 if (res) |
| 231 pmd->set_has_process_mmaps(); | 239 pmd->set_has_process_mmaps(); |
| 232 return res; | 240 return res; |
| 233 } | 241 } |
| 234 #endif // defined(OS_LINUX) || defined(OS_ANDROID) | 242 #endif // defined(OS_LINUX) || defined(OS_ANDROID) |
| 235 | 243 |
| 244 #if defined(OS_WIN) | |
| 245 bool ProcessMetricsMemoryDumpProvider::DumpProcessMemoryMaps( | |
| 246 const base::trace_event::MemoryDumpArgs& args, | |
| 247 base::trace_event::ProcessMemoryDump* pmd) { | |
| 248 // Fetch handles to each of the modules loaded in this process. The process | |
| 249 // itself retains ownership of the returned handles. | |
| 250 DWORD requested_module_count = 1024; | |
| 251 DWORD result_module_count = 0; | |
| 252 std::vector<HMODULE> modules; | |
| 253 while (true) { | |
| 254 modules.resize(requested_module_count); | |
| 255 DWORD output_size = 0; | |
| 256 BOOL result = ::EnumProcessModules(::GetCurrentProcess(), modules.data(), | |
| 257 requested_module_count * sizeof(HMODULE), | |
| 258 &output_size); | |
| 259 if (!result) | |
| 260 return false; | |
| 261 result_module_count = output_size / sizeof(HMODULE); | |
|
etienneb
2017/02/23 21:11:36
The way we were used to handle these racy windows
erikchen
2017/02/23 21:33:33
Sorry, I don't understand what you mean. AFAICT, t
etienneb
2017/02/24 16:37:15
I'm fine with the switch. thx.
| |
| 262 | |
| 263 if (result_module_count <= requested_module_count) | |
| 264 break; | |
| 265 | |
| 266 // Try again. Add a small buffer, since ::EnumProcessModules can be racy. | |
| 267 requested_module_count = result_module_count + 5; | |
| 268 } | |
| 269 | |
| 270 // Query the base address for each module, and attach it to the dump. | |
| 271 for (DWORD i = 0; i < result_module_count; ++i) { | |
| 272 wchar_t module_name[MAX_PATH]; | |
| 273 BOOL result = ::GetModuleFileName(modules[i], module_name, MAX_PATH); | |
| 274 if (!result) | |
| 275 continue; | |
| 276 | |
| 277 MODULEINFO module_info; | |
| 278 result = ::GetModuleInformation(::GetCurrentProcess(), modules[i], | |
| 279 &module_info, sizeof(MODULEINFO)); | |
| 280 if (!result) | |
| 281 continue; | |
| 282 base::trace_event::ProcessMemoryMaps::VMRegion region; | |
| 283 region.size_in_bytes = module_info.SizeOfImage; | |
| 284 region.mapped_file = base::SysWideToNativeMB(module_name); | |
| 285 region.start_address = reinterpret_cast<uint64_t>(module_info.lpBaseOfDll); | |
| 286 pmd->process_mmaps()->AddVMRegion(region); | |
| 287 } | |
| 288 if (!pmd->process_mmaps()->vm_regions().empty()) | |
| 289 pmd->set_has_process_mmaps(); | |
| 290 return true; | |
| 291 } | |
| 292 #endif // defined(OS_WIN) | |
| 293 | |
| 236 #if defined(OS_MACOSX) | 294 #if defined(OS_MACOSX) |
| 237 | 295 |
| 238 namespace { | 296 namespace { |
| 239 | 297 |
| 240 using VMRegion = base::trace_event::ProcessMemoryMaps::VMRegion; | 298 using VMRegion = base::trace_event::ProcessMemoryMaps::VMRegion; |
| 241 | 299 |
| 242 bool IsAddressInSharedRegion(uint64_t address) { | 300 bool IsAddressInSharedRegion(uint64_t address) { |
| 243 return address >= SHARED_REGION_BASE_X86_64 && | 301 return address >= SHARED_REGION_BASE_X86_64 && |
| 244 address < (SHARED_REGION_BASE_X86_64 + SHARED_REGION_SIZE_X86_64); | 302 address < (SHARED_REGION_BASE_X86_64 + SHARED_REGION_SIZE_X86_64); |
| 245 } | 303 } |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 540 | 598 |
| 541 ProcessMetricsMemoryDumpProvider::~ProcessMetricsMemoryDumpProvider() {} | 599 ProcessMetricsMemoryDumpProvider::~ProcessMetricsMemoryDumpProvider() {} |
| 542 | 600 |
| 543 // Called at trace dump point time. Creates a snapshot of the memory maps for | 601 // Called at trace dump point time. Creates a snapshot of the memory maps for |
| 544 // the current process. | 602 // the current process. |
| 545 bool ProcessMetricsMemoryDumpProvider::OnMemoryDump( | 603 bool ProcessMetricsMemoryDumpProvider::OnMemoryDump( |
| 546 const base::trace_event::MemoryDumpArgs& args, | 604 const base::trace_event::MemoryDumpArgs& args, |
| 547 base::trace_event::ProcessMemoryDump* pmd) { | 605 base::trace_event::ProcessMemoryDump* pmd) { |
| 548 bool res = DumpProcessTotals(args, pmd); | 606 bool res = DumpProcessTotals(args, pmd); |
| 549 | 607 |
| 550 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX) | |
| 551 if (args.level_of_detail == | 608 if (args.level_of_detail == |
| 552 base::trace_event::MemoryDumpLevelOfDetail::DETAILED) | 609 base::trace_event::MemoryDumpLevelOfDetail::DETAILED) |
| 553 res &= DumpProcessMemoryMaps(args, pmd); | 610 res &= DumpProcessMemoryMaps(args, pmd); |
| 554 #endif // defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX) | |
| 555 return res; | 611 return res; |
| 556 } | 612 } |
| 557 | 613 |
| 558 bool ProcessMetricsMemoryDumpProvider::DumpProcessTotals( | 614 bool ProcessMetricsMemoryDumpProvider::DumpProcessTotals( |
| 559 const base::trace_event::MemoryDumpArgs& args, | 615 const base::trace_event::MemoryDumpArgs& args, |
| 560 base::trace_event::ProcessMemoryDump* pmd) { | 616 base::trace_event::ProcessMemoryDump* pmd) { |
| 561 const uint64_t rss_bytes = rss_bytes_for_testing | 617 const uint64_t rss_bytes = rss_bytes_for_testing |
| 562 ? rss_bytes_for_testing | 618 ? rss_bytes_for_testing |
| 563 : process_metrics_->GetWorkingSetSize(); | 619 : process_metrics_->GetWorkingSetSize(); |
| 564 | 620 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 #endif | 703 #endif |
| 648 } | 704 } |
| 649 | 705 |
| 650 void ProcessMetricsMemoryDumpProvider::SuspendFastMemoryPolling() { | 706 void ProcessMetricsMemoryDumpProvider::SuspendFastMemoryPolling() { |
| 651 #if defined(OS_LINUX) || defined(OS_ANDROID) | 707 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| 652 fast_polling_statm_fd_.reset(); | 708 fast_polling_statm_fd_.reset(); |
| 653 #endif | 709 #endif |
| 654 } | 710 } |
| 655 | 711 |
| 656 } // namespace tracing | 712 } // namespace tracing |
| OLD | NEW |