OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 | |
6 #include "base/process_util.h" | 5 #include "base/process_util.h" |
7 | 6 |
8 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
9 #include <crt_externs.h> | 8 #include <crt_externs.h> |
10 #include <dlfcn.h> | 9 #include <dlfcn.h> |
11 #include <mach/mach.h> | 10 #include <mach/mach.h> |
12 #include <mach/mach_init.h> | 11 #include <mach/mach_init.h> |
13 #include <mach/mach_vm.h> | 12 #include <mach/mach_vm.h> |
14 #include <mach/shared_region.h> | 13 #include <mach/shared_region.h> |
15 #include <mach/task.h> | 14 #include <mach/task.h> |
16 #include <malloc/malloc.h> | 15 #include <malloc/malloc.h> |
17 #import <objc/runtime.h> | 16 #import <objc/runtime.h> |
18 #include <spawn.h> | 17 #include <spawn.h> |
19 #include <sys/mman.h> | 18 #include <sys/mman.h> |
20 #include <sys/sysctl.h> | 19 #include <sys/sysctl.h> |
21 #include <sys/types.h> | 20 #include <sys/types.h> |
22 #include <sys/utsname.h> | |
23 #include <sys/wait.h> | 21 #include <sys/wait.h> |
24 | 22 |
25 #include <new> | 23 #include <new> |
26 #include <string> | 24 #include <string> |
27 | 25 |
28 #include "base/debug/debugger.h" | 26 #include "base/debug/debugger.h" |
29 #include "base/eintr_wrapper.h" | 27 #include "base/eintr_wrapper.h" |
30 #include "base/hash_tables.h" | 28 #include "base/hash_tables.h" |
31 #include "base/logging.h" | 29 #include "base/logging.h" |
| 30 #include "base/mac/mac_util.h" |
32 #include "base/string_util.h" | 31 #include "base/string_util.h" |
33 #include "base/sys_info.h" | 32 #include "base/sys_info.h" |
34 #include "base/sys_string_conversions.h" | 33 #include "base/sys_string_conversions.h" |
35 #include "base/time.h" | 34 #include "base/time.h" |
36 #include "third_party/apple_apsl/CFBase.h" | 35 #include "third_party/apple_apsl/CFBase.h" |
37 #include "third_party/apple_apsl/malloc.h" | 36 #include "third_party/apple_apsl/malloc.h" |
38 | 37 |
39 namespace base { | 38 namespace base { |
40 | 39 |
41 void RestoreDefaultExceptionHandler() { | 40 void RestoreDefaultExceptionHandler() { |
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 } | 614 } |
616 | 615 |
617 // === C++ operator new === | 616 // === C++ operator new === |
618 | 617 |
619 void oom_killer_new() { | 618 void oom_killer_new() { |
620 debug::BreakDebugger(); | 619 debug::BreakDebugger(); |
621 } | 620 } |
622 | 621 |
623 // === Core Foundation CFAllocators === | 622 // === Core Foundation CFAllocators === |
624 | 623 |
625 bool CanGetContextForCFAllocator(long darwin_version) { | 624 bool CanGetContextForCFAllocator() { |
626 // TODO(avi): remove at final release; http://crbug.com/74589 | 625 // TODO(avi): remove at final release; http://crbug.com/74589 |
627 if (darwin_version == 11) { | 626 if (base::mac::IsOSLion()) { |
628 NSLog(@"Unsure about the internals of CFAllocator but going to patch them " | 627 NSLog(@"Unsure about the internals of CFAllocator but going to patch them " |
629 "anyway. Watch out for crashes inside of CFAllocatorAllocate."); | 628 "anyway. Watch out for crashes inside of CFAllocatorAllocate."); |
630 } | 629 } |
631 return darwin_version == 9 || | 630 return !base::mac::IsOSLaterThanLion(); |
632 darwin_version == 10 || | |
633 darwin_version == 11; | |
634 } | 631 } |
635 | 632 |
636 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator, | 633 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { |
637 long darwin_version) { | 634 if (base::mac::IsOSLeopard() || base::mac::IsOSSnowLeopard()) { |
638 if (darwin_version == 9 || darwin_version == 10) { | 635 ChromeCFAllocatorLeopards* our_allocator = |
639 ChromeCFAllocator9and10* our_allocator = | 636 const_cast<ChromeCFAllocatorLeopards*>( |
640 const_cast<ChromeCFAllocator9and10*>( | 637 reinterpret_cast<const ChromeCFAllocatorLeopards*>(allocator)); |
641 reinterpret_cast<const ChromeCFAllocator9and10*>(allocator)); | |
642 return &our_allocator->_context; | 638 return &our_allocator->_context; |
643 } else if (darwin_version == 11) { | 639 } else if (base::mac::IsOSLion()) { |
644 ChromeCFAllocator11* our_allocator = | 640 ChromeCFAllocatorLion* our_allocator = |
645 const_cast<ChromeCFAllocator11*>( | 641 const_cast<ChromeCFAllocatorLion*>( |
646 reinterpret_cast<const ChromeCFAllocator11*>(allocator)); | 642 reinterpret_cast<const ChromeCFAllocatorLion*>(allocator)); |
647 return &our_allocator->_context; | 643 return &our_allocator->_context; |
648 } else { | 644 } else { |
649 return NULL; | 645 return NULL; |
650 } | 646 } |
651 } | 647 } |
652 | 648 |
653 CFAllocatorAllocateCallBack g_old_cfallocator_system_default; | 649 CFAllocatorAllocateCallBack g_old_cfallocator_system_default; |
654 CFAllocatorAllocateCallBack g_old_cfallocator_malloc; | 650 CFAllocatorAllocateCallBack g_old_cfallocator_malloc; |
655 CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; | 651 CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; |
656 | 652 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 return malloc_purgeable_zone(); | 703 return malloc_purgeable_zone(); |
708 return NULL; | 704 return NULL; |
709 } | 705 } |
710 | 706 |
711 void EnableTerminationOnOutOfMemory() { | 707 void EnableTerminationOnOutOfMemory() { |
712 if (g_oom_killer_enabled) | 708 if (g_oom_killer_enabled) |
713 return; | 709 return; |
714 | 710 |
715 g_oom_killer_enabled = true; | 711 g_oom_killer_enabled = true; |
716 | 712 |
717 // Not SysInfo::OperatingSystemVersionNumbers as that calls through to Gestalt | |
718 // which ends up (on > 10.6) spawning threads. | |
719 struct utsname machine_info; | |
720 if (uname(&machine_info)) { | |
721 return; | |
722 } | |
723 | |
724 // The string machine_info.release is the xnu/Darwin version number, "9.xxx" | |
725 // on Mac OS X 10.5, and "10.xxx" on Mac OS X 10.6. See | |
726 // http://en.wikipedia.org/wiki/Darwin_(operating_system) . | |
727 long darwin_version = strtol(machine_info.release, NULL, 10); | |
728 | |
729 // === C malloc/calloc/valloc/realloc/posix_memalign === | 713 // === C malloc/calloc/valloc/realloc/posix_memalign === |
730 | 714 |
731 // This approach is not perfect, as requests for amounts of memory larger than | 715 // This approach is not perfect, as requests for amounts of memory larger than |
732 // MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will | 716 // MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will |
733 // still fail with a NULL rather than dying (see | 717 // still fail with a NULL rather than dying (see |
734 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). | 718 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). |
735 // Unfortunately, it's the best we can do. Also note that this does not affect | 719 // Unfortunately, it's the best we can do. Also note that this does not affect |
736 // allocations from non-default zones. | 720 // allocations from non-default zones. |
737 | 721 |
738 CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && | 722 CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && |
739 !g_old_memalign) << "Old allocators unexpectedly non-null"; | 723 !g_old_memalign) << "Old allocators unexpectedly non-null"; |
740 | 724 |
741 CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && | 725 CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && |
742 !g_old_valloc_purgeable && !g_old_realloc_purgeable && | 726 !g_old_valloc_purgeable && !g_old_realloc_purgeable && |
743 !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; | 727 !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; |
744 | 728 |
745 // See http://trac.webkit.org/changeset/53362/trunk/Tools/DumpRenderTree/mac | 729 // See http://trac.webkit.org/changeset/53362/trunk/Tools/DumpRenderTree/mac |
746 bool zone_allocators_protected = darwin_version > 10; | 730 bool zone_allocators_protected = base::mac::IsOSLionOrLater(); |
747 | 731 |
748 ChromeMallocZone* default_zone = | 732 ChromeMallocZone* default_zone = |
749 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); | 733 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); |
750 ChromeMallocZone* purgeable_zone = | 734 ChromeMallocZone* purgeable_zone = |
751 reinterpret_cast<ChromeMallocZone*>(GetPurgeableZone()); | 735 reinterpret_cast<ChromeMallocZone*>(GetPurgeableZone()); |
752 | 736 |
753 vm_address_t page_start_default = NULL; | 737 vm_address_t page_start_default = NULL; |
754 vm_address_t page_start_purgeable = NULL; | 738 vm_address_t page_start_purgeable = NULL; |
755 vm_size_t len_default = 0; | 739 vm_size_t len_default = 0; |
756 vm_size_t len_purgeable = 0; | 740 vm_size_t len_purgeable = 0; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 | 835 |
852 // === Core Foundation CFAllocators === | 836 // === Core Foundation CFAllocators === |
853 | 837 |
854 // This will not catch allocation done by custom allocators, but will catch | 838 // This will not catch allocation done by custom allocators, but will catch |
855 // all allocation done by system-provided ones. | 839 // all allocation done by system-provided ones. |
856 | 840 |
857 CHECK(!g_old_cfallocator_system_default && !g_old_cfallocator_malloc && | 841 CHECK(!g_old_cfallocator_system_default && !g_old_cfallocator_malloc && |
858 !g_old_cfallocator_malloc_zone) | 842 !g_old_cfallocator_malloc_zone) |
859 << "Old allocators unexpectedly non-null"; | 843 << "Old allocators unexpectedly non-null"; |
860 | 844 |
861 bool cf_allocator_internals_known = | 845 bool cf_allocator_internals_known = CanGetContextForCFAllocator(); |
862 CanGetContextForCFAllocator(darwin_version); | |
863 | 846 |
864 if (cf_allocator_internals_known) { | 847 if (cf_allocator_internals_known) { |
865 CFAllocatorContext* context = | 848 CFAllocatorContext* context = |
866 ContextForCFAllocator(kCFAllocatorSystemDefault, darwin_version); | 849 ContextForCFAllocator(kCFAllocatorSystemDefault); |
867 CHECK(context) << "Failed to get context for kCFAllocatorSystemDefault."; | 850 CHECK(context) << "Failed to get context for kCFAllocatorSystemDefault."; |
868 g_old_cfallocator_system_default = context->allocate; | 851 g_old_cfallocator_system_default = context->allocate; |
869 CHECK(g_old_cfallocator_system_default) | 852 CHECK(g_old_cfallocator_system_default) |
870 << "Failed to get kCFAllocatorSystemDefault allocation function."; | 853 << "Failed to get kCFAllocatorSystemDefault allocation function."; |
871 context->allocate = oom_killer_cfallocator_system_default; | 854 context->allocate = oom_killer_cfallocator_system_default; |
872 | 855 |
873 context = ContextForCFAllocator(kCFAllocatorMalloc, darwin_version); | 856 context = ContextForCFAllocator(kCFAllocatorMalloc); |
874 CHECK(context) << "Failed to get context for kCFAllocatorMalloc."; | 857 CHECK(context) << "Failed to get context for kCFAllocatorMalloc."; |
875 g_old_cfallocator_malloc = context->allocate; | 858 g_old_cfallocator_malloc = context->allocate; |
876 CHECK(g_old_cfallocator_malloc) | 859 CHECK(g_old_cfallocator_malloc) |
877 << "Failed to get kCFAllocatorMalloc allocation function."; | 860 << "Failed to get kCFAllocatorMalloc allocation function."; |
878 context->allocate = oom_killer_cfallocator_malloc; | 861 context->allocate = oom_killer_cfallocator_malloc; |
879 | 862 |
880 context = ContextForCFAllocator(kCFAllocatorMallocZone, darwin_version); | 863 context = ContextForCFAllocator(kCFAllocatorMallocZone); |
881 CHECK(context) << "Failed to get context for kCFAllocatorMallocZone."; | 864 CHECK(context) << "Failed to get context for kCFAllocatorMallocZone."; |
882 g_old_cfallocator_malloc_zone = context->allocate; | 865 g_old_cfallocator_malloc_zone = context->allocate; |
883 CHECK(g_old_cfallocator_malloc_zone) | 866 CHECK(g_old_cfallocator_malloc_zone) |
884 << "Failed to get kCFAllocatorMallocZone allocation function."; | 867 << "Failed to get kCFAllocatorMallocZone allocation function."; |
885 context->allocate = oom_killer_cfallocator_malloc_zone; | 868 context->allocate = oom_killer_cfallocator_malloc_zone; |
886 } else { | 869 } else { |
887 NSLog(@"Internals of CFAllocator not known; out-of-memory failures via " | 870 NSLog(@"Internals of CFAllocator not known; out-of-memory failures via " |
888 "CFAllocator will not result in termination. http://crbug.com/45650"); | 871 "CFAllocator will not result in termination. http://crbug.com/45650"); |
889 } | 872 } |
890 | 873 |
(...skipping 23 matching lines...) Expand all Loading... |
914 if (sysctl(mib, 4, &info, &length, NULL, 0) < 0) { | 897 if (sysctl(mib, 4, &info, &length, NULL, 0) < 0) { |
915 PLOG(ERROR) << "sysctl"; | 898 PLOG(ERROR) << "sysctl"; |
916 return -1; | 899 return -1; |
917 } | 900 } |
918 if (length == 0) | 901 if (length == 0) |
919 return -1; | 902 return -1; |
920 return info.kp_eproc.e_ppid; | 903 return info.kp_eproc.e_ppid; |
921 } | 904 } |
922 | 905 |
923 } // namespace base | 906 } // namespace base |
OLD | NEW |