OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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 | 5 |
6 #include "base/process_util.h" | 6 #include "base/process_util.h" |
7 | 7 |
8 #import <Cocoa/Cocoa.h> | 8 #import <Cocoa/Cocoa.h> |
9 #include <crt_externs.h> | 9 #include <crt_externs.h> |
10 #include <dlfcn.h> | 10 #include <dlfcn.h> |
11 #include <mach/mach.h> | 11 #include <mach/mach.h> |
12 #include <mach/mach_init.h> | 12 #include <mach/mach_init.h> |
13 #include <mach/task.h> | 13 #include <mach/task.h> |
14 #include <malloc/malloc.h> | 14 #include <malloc/malloc.h> |
15 #import <objc/runtime.h> | 15 #import <objc/runtime.h> |
16 #include <spawn.h> | 16 #include <spawn.h> |
17 #include <sys/mman.h> | 17 #include <sys/mman.h> |
18 #include <sys/sysctl.h> | 18 #include <sys/sysctl.h> |
19 #include <sys/types.h> | 19 #include <sys/types.h> |
20 #include <sys/utsname.h> | 20 #include <sys/utsname.h> |
21 #include <sys/wait.h> | 21 #include <sys/wait.h> |
22 | 22 |
23 #include <new> | 23 #include <new> |
24 #include <string> | 24 #include <string> |
25 | 25 |
26 #include "base/debug_util.h" | 26 #include "base/debug/debugger.h" |
27 #include "base/eintr_wrapper.h" | 27 #include "base/eintr_wrapper.h" |
28 #include "base/logging.h" | 28 #include "base/logging.h" |
29 #include "base/string_util.h" | 29 #include "base/string_util.h" |
30 #include "base/sys_info.h" | 30 #include "base/sys_info.h" |
31 #include "base/sys_string_conversions.h" | 31 #include "base/sys_string_conversions.h" |
32 #include "base/time.h" | 32 #include "base/time.h" |
33 #include "third_party/apple_apsl/CFBase.h" | 33 #include "third_party/apple_apsl/CFBase.h" |
34 #include "third_party/apple_apsl/malloc.h" | 34 #include "third_party/apple_apsl/malloc.h" |
35 | 35 |
36 namespace base { | 36 namespace base { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 exec_name_end - last_slash - 1); | 159 exec_name_end - last_slash - 1); |
160 // Start w/ the next entry next time through | 160 // Start w/ the next entry next time through |
161 ++index_of_kinfo_proc_; | 161 ++index_of_kinfo_proc_; |
162 // Done | 162 // Done |
163 return true; | 163 return true; |
164 } | 164 } |
165 return false; | 165 return false; |
166 } | 166 } |
167 | 167 |
168 bool NamedProcessIterator::IncludeEntry() { | 168 bool NamedProcessIterator::IncludeEntry() { |
169 return (base::SysWideToUTF8(executable_name_) == entry().exe_file() && | 169 return (SysWideToUTF8(executable_name_) == entry().exe_file() && |
170 ProcessIterator::IncludeEntry()); | 170 ProcessIterator::IncludeEntry()); |
171 } | 171 } |
172 | 172 |
173 | 173 |
174 // ------------------------------------------------------------------------ | 174 // ------------------------------------------------------------------------ |
175 // NOTE: about ProcessMetrics | 175 // NOTE: about ProcessMetrics |
176 // | 176 // |
177 // Getting a mach task from a pid for another process requires permissions in | 177 // Getting a mach task from a pid for another process requires permissions in |
178 // general, so there doesn't really seem to be a way to do these (and spinning | 178 // general, so there doesn't really seem to be a way to do these (and spinning |
179 // up ps to fetch each stats seems dangerous to put in a base api for anyone to | 179 // up ps to fetch each stats seems dangerous to put in a base api for anyone to |
180 // call). Child processes ipc their port, so return something if available, | 180 // call). Child processes ipc their port, so return something if available, |
181 // otherwise return 0. | 181 // otherwise return 0. |
182 // | 182 // |
183 | 183 |
184 ProcessMetrics::ProcessMetrics(ProcessHandle process, | 184 ProcessMetrics::ProcessMetrics(ProcessHandle process, |
185 ProcessMetrics::PortProvider* port_provider) | 185 ProcessMetrics::PortProvider* port_provider) |
186 : process_(process), | 186 : process_(process), |
187 last_time_(0), | 187 last_time_(0), |
188 last_system_time_(0), | 188 last_system_time_(0), |
189 port_provider_(port_provider) { | 189 port_provider_(port_provider) { |
190 processor_count_ = base::SysInfo::NumberOfProcessors(); | 190 processor_count_ = SysInfo::NumberOfProcessors(); |
191 } | 191 } |
192 | 192 |
193 // static | 193 // static |
194 ProcessMetrics* ProcessMetrics::CreateProcessMetrics( | 194 ProcessMetrics* ProcessMetrics::CreateProcessMetrics( |
195 ProcessHandle process, | 195 ProcessHandle process, |
196 ProcessMetrics::PortProvider* port_provider) { | 196 ProcessMetrics::PortProvider* port_provider) { |
197 return new ProcessMetrics(process, port_provider); | 197 return new ProcessMetrics(process, port_provider); |
198 } | 198 } |
199 | 199 |
200 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { | 200 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 malloc_type g_old_malloc_purgeable; | 395 malloc_type g_old_malloc_purgeable; |
396 calloc_type g_old_calloc_purgeable; | 396 calloc_type g_old_calloc_purgeable; |
397 valloc_type g_old_valloc_purgeable; | 397 valloc_type g_old_valloc_purgeable; |
398 realloc_type g_old_realloc_purgeable; | 398 realloc_type g_old_realloc_purgeable; |
399 memalign_type g_old_memalign_purgeable; | 399 memalign_type g_old_memalign_purgeable; |
400 | 400 |
401 void* oom_killer_malloc(struct _malloc_zone_t* zone, | 401 void* oom_killer_malloc(struct _malloc_zone_t* zone, |
402 size_t size) { | 402 size_t size) { |
403 void* result = g_old_malloc(zone, size); | 403 void* result = g_old_malloc(zone, size); |
404 if (!result && size) | 404 if (!result && size) |
405 DebugUtil::BreakDebugger(); | 405 debugger::BreakDebugger(); |
406 return result; | 406 return result; |
407 } | 407 } |
408 | 408 |
409 void* oom_killer_calloc(struct _malloc_zone_t* zone, | 409 void* oom_killer_calloc(struct _malloc_zone_t* zone, |
410 size_t num_items, | 410 size_t num_items, |
411 size_t size) { | 411 size_t size) { |
412 void* result = g_old_calloc(zone, num_items, size); | 412 void* result = g_old_calloc(zone, num_items, size); |
413 if (!result && num_items && size) | 413 if (!result && num_items && size) |
414 DebugUtil::BreakDebugger(); | 414 debugger::BreakDebugger(); |
415 return result; | 415 return result; |
416 } | 416 } |
417 | 417 |
418 void* oom_killer_valloc(struct _malloc_zone_t* zone, | 418 void* oom_killer_valloc(struct _malloc_zone_t* zone, |
419 size_t size) { | 419 size_t size) { |
420 void* result = g_old_valloc(zone, size); | 420 void* result = g_old_valloc(zone, size); |
421 if (!result && size) | 421 if (!result && size) |
422 DebugUtil::BreakDebugger(); | 422 debugger::BreakDebugger(); |
423 return result; | 423 return result; |
424 } | 424 } |
425 | 425 |
426 void* oom_killer_realloc(struct _malloc_zone_t* zone, | 426 void* oom_killer_realloc(struct _malloc_zone_t* zone, |
427 void* ptr, | 427 void* ptr, |
428 size_t size) { | 428 size_t size) { |
429 void* result = g_old_realloc(zone, ptr, size); | 429 void* result = g_old_realloc(zone, ptr, size); |
430 if (!result && size) | 430 if (!result && size) |
431 DebugUtil::BreakDebugger(); | 431 debugger::BreakDebugger(); |
432 return result; | 432 return result; |
433 } | 433 } |
434 | 434 |
435 void* oom_killer_memalign(struct _malloc_zone_t* zone, | 435 void* oom_killer_memalign(struct _malloc_zone_t* zone, |
436 size_t alignment, | 436 size_t alignment, |
437 size_t size) { | 437 size_t size) { |
438 void* result = g_old_memalign(zone, alignment, size); | 438 void* result = g_old_memalign(zone, alignment, size); |
439 // Only die if posix_memalign would have returned ENOMEM, since there are | 439 // Only die if posix_memalign would have returned ENOMEM, since there are |
440 // other reasons why NULL might be returned (see | 440 // other reasons why NULL might be returned (see |
441 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 441 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
442 if (!result && size && alignment >= sizeof(void*) | 442 if (!result && size && alignment >= sizeof(void*) |
443 && (alignment & (alignment - 1)) == 0) { | 443 && (alignment & (alignment - 1)) == 0) { |
444 DebugUtil::BreakDebugger(); | 444 debugger::BreakDebugger(); |
445 } | 445 } |
446 return result; | 446 return result; |
447 } | 447 } |
448 | 448 |
449 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, | 449 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, |
450 size_t size) { | 450 size_t size) { |
451 void* result = g_old_malloc_purgeable(zone, size); | 451 void* result = g_old_malloc_purgeable(zone, size); |
452 if (!result && size) | 452 if (!result && size) |
453 DebugUtil::BreakDebugger(); | 453 debugger::BreakDebugger(); |
454 return result; | 454 return result; |
455 } | 455 } |
456 | 456 |
457 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, | 457 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, |
458 size_t num_items, | 458 size_t num_items, |
459 size_t size) { | 459 size_t size) { |
460 void* result = g_old_calloc_purgeable(zone, num_items, size); | 460 void* result = g_old_calloc_purgeable(zone, num_items, size); |
461 if (!result && num_items && size) | 461 if (!result && num_items && size) |
462 DebugUtil::BreakDebugger(); | 462 debugger::BreakDebugger(); |
463 return result; | 463 return result; |
464 } | 464 } |
465 | 465 |
466 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, | 466 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, |
467 size_t size) { | 467 size_t size) { |
468 void* result = g_old_valloc_purgeable(zone, size); | 468 void* result = g_old_valloc_purgeable(zone, size); |
469 if (!result && size) | 469 if (!result && size) |
470 DebugUtil::BreakDebugger(); | 470 debugger::BreakDebugger(); |
471 return result; | 471 return result; |
472 } | 472 } |
473 | 473 |
474 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, | 474 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, |
475 void* ptr, | 475 void* ptr, |
476 size_t size) { | 476 size_t size) { |
477 void* result = g_old_realloc_purgeable(zone, ptr, size); | 477 void* result = g_old_realloc_purgeable(zone, ptr, size); |
478 if (!result && size) | 478 if (!result && size) |
479 DebugUtil::BreakDebugger(); | 479 debugger::BreakDebugger(); |
480 return result; | 480 return result; |
481 } | 481 } |
482 | 482 |
483 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, | 483 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, |
484 size_t alignment, | 484 size_t alignment, |
485 size_t size) { | 485 size_t size) { |
486 void* result = g_old_memalign_purgeable(zone, alignment, size); | 486 void* result = g_old_memalign_purgeable(zone, alignment, size); |
487 // Only die if posix_memalign would have returned ENOMEM, since there are | 487 // Only die if posix_memalign would have returned ENOMEM, since there are |
488 // other reasons why NULL might be returned (see | 488 // other reasons why NULL might be returned (see |
489 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 489 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
490 if (!result && size && alignment >= sizeof(void*) | 490 if (!result && size && alignment >= sizeof(void*) |
491 && (alignment & (alignment - 1)) == 0) { | 491 && (alignment & (alignment - 1)) == 0) { |
492 DebugUtil::BreakDebugger(); | 492 debugger::BreakDebugger(); |
493 } | 493 } |
494 return result; | 494 return result; |
495 } | 495 } |
496 | 496 |
497 // === C++ operator new === | 497 // === C++ operator new === |
498 | 498 |
499 void oom_killer_new() { | 499 void oom_killer_new() { |
500 DebugUtil::BreakDebugger(); | 500 debugger::BreakDebugger(); |
501 } | 501 } |
502 | 502 |
503 // === Core Foundation CFAllocators === | 503 // === Core Foundation CFAllocators === |
504 | 504 |
505 typedef ChromeCFAllocator* ChromeCFAllocatorRef; | 505 typedef ChromeCFAllocator* ChromeCFAllocatorRef; |
506 | 506 |
507 CFAllocatorAllocateCallBack g_old_cfallocator_system_default; | 507 CFAllocatorAllocateCallBack g_old_cfallocator_system_default; |
508 CFAllocatorAllocateCallBack g_old_cfallocator_malloc; | 508 CFAllocatorAllocateCallBack g_old_cfallocator_malloc; |
509 CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; | 509 CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; |
510 | 510 |
511 void* oom_killer_cfallocator_system_default(CFIndex alloc_size, | 511 void* oom_killer_cfallocator_system_default(CFIndex alloc_size, |
512 CFOptionFlags hint, | 512 CFOptionFlags hint, |
513 void* info) { | 513 void* info) { |
514 void* result = g_old_cfallocator_system_default(alloc_size, hint, info); | 514 void* result = g_old_cfallocator_system_default(alloc_size, hint, info); |
515 if (!result) | 515 if (!result) |
516 DebugUtil::BreakDebugger(); | 516 debugger::BreakDebugger(); |
517 return result; | 517 return result; |
518 } | 518 } |
519 | 519 |
520 void* oom_killer_cfallocator_malloc(CFIndex alloc_size, | 520 void* oom_killer_cfallocator_malloc(CFIndex alloc_size, |
521 CFOptionFlags hint, | 521 CFOptionFlags hint, |
522 void* info) { | 522 void* info) { |
523 void* result = g_old_cfallocator_malloc(alloc_size, hint, info); | 523 void* result = g_old_cfallocator_malloc(alloc_size, hint, info); |
524 if (!result) | 524 if (!result) |
525 DebugUtil::BreakDebugger(); | 525 debugger::BreakDebugger(); |
526 return result; | 526 return result; |
527 } | 527 } |
528 | 528 |
529 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, | 529 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, |
530 CFOptionFlags hint, | 530 CFOptionFlags hint, |
531 void* info) { | 531 void* info) { |
532 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); | 532 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); |
533 if (!result) | 533 if (!result) |
534 DebugUtil::BreakDebugger(); | 534 debugger::BreakDebugger(); |
535 return result; | 535 return result; |
536 } | 536 } |
537 | 537 |
538 // === Cocoa NSObject allocation === | 538 // === Cocoa NSObject allocation === |
539 | 539 |
540 typedef id (*allocWithZone_t)(id, SEL, NSZone*); | 540 typedef id (*allocWithZone_t)(id, SEL, NSZone*); |
541 allocWithZone_t g_old_allocWithZone; | 541 allocWithZone_t g_old_allocWithZone; |
542 | 542 |
543 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) | 543 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) |
544 { | 544 { |
545 id result = g_old_allocWithZone(self, _cmd, zone); | 545 id result = g_old_allocWithZone(self, _cmd, zone); |
546 if (!result) | 546 if (!result) |
547 DebugUtil::BreakDebugger(); | 547 debugger::BreakDebugger(); |
548 return result; | 548 return result; |
549 } | 549 } |
550 | 550 |
551 } // namespace | 551 } // namespace |
552 | 552 |
553 malloc_zone_t* GetPurgeableZone() { | 553 malloc_zone_t* GetPurgeableZone() { |
554 // malloc_default_purgeable_zone only exists on >= 10.6. Use dlsym to grab it | 554 // malloc_default_purgeable_zone only exists on >= 10.6. Use dlsym to grab it |
555 // at runtime because it may not be present in the SDK used for compilation. | 555 // at runtime because it may not be present in the SDK used for compilation. |
556 typedef malloc_zone_t* (*malloc_default_purgeable_zone_t)(void); | 556 typedef malloc_zone_t* (*malloc_default_purgeable_zone_t)(void); |
557 malloc_default_purgeable_zone_t malloc_purgeable_zone = | 557 malloc_default_purgeable_zone_t malloc_purgeable_zone = |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 @selector(allocWithZone:)); | 754 @selector(allocWithZone:)); |
755 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( | 755 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( |
756 method_getImplementation(orig_method)); | 756 method_getImplementation(orig_method)); |
757 CHECK(g_old_allocWithZone) | 757 CHECK(g_old_allocWithZone) |
758 << "Failed to get allocWithZone allocation function."; | 758 << "Failed to get allocWithZone allocation function."; |
759 method_setImplementation(orig_method, | 759 method_setImplementation(orig_method, |
760 reinterpret_cast<IMP>(oom_killer_allocWithZone)); | 760 reinterpret_cast<IMP>(oom_killer_allocWithZone)); |
761 } | 761 } |
762 | 762 |
763 } // namespace base | 763 } // namespace base |
OLD | NEW |