Chromium Code Reviews| Index: base/process_util_mac.mm |
| diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm |
| index b257021401726975aa33eb3fc7cc96b140964141..9e1ec37c34348fd5177e592b426e46c5e2506f05 100644 |
| --- a/base/process_util_mac.mm |
| +++ b/base/process_util_mac.mm |
| @@ -13,7 +13,6 @@ |
| #include <mach/mach_vm.h> |
| #include <mach/shared_region.h> |
| #include <mach/task.h> |
| -#include <mach-o/dyld.h> |
| #include <mach-o/nlist.h> |
| #include <malloc/malloc.h> |
| #import <objc/runtime.h> |
| @@ -32,12 +31,12 @@ |
| #include "base/eintr_wrapper.h" |
| #include "base/file_util.h" |
| #include "base/hash_tables.h" |
| +#include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/mac/mac_util.h" |
| #include "base/string_util.h" |
| #include "base/sys_info.h" |
| -#include "base/sys_string_conversions.h" |
| -#include "base/time.h" |
| +#include "base/threading/thread_local.h" |
| #include "third_party/apple_apsl/CFBase.h" |
| #include "third_party/apple_apsl/malloc.h" |
| #include "third_party/mach_override/mach_override.h" |
| @@ -566,20 +565,45 @@ class ScopedClearErrno { |
| DISALLOW_COPY_AND_ASSIGN(ScopedClearErrno); |
| }; |
| +// Combines ThreadLocalBoolean with AutoReset. It would be convenient |
| +// to compose ThreadLocalPointer<bool> with AutoReset<bool>, but that |
| +// would require allocating some storage for the bool. |
| +class ThreadLocalBooleanAutoReset { |
| + public: |
| + ThreadLocalBooleanAutoReset(ThreadLocalBoolean* tlb, bool new_value) |
| + : scoped_tlb_(tlb), |
| + original_value_(tlb->Get()) { |
| + scoped_tlb_->Set(new_value); |
| + } |
| + ~ThreadLocalBooleanAutoReset() { |
| + scoped_tlb_->Set(original_value_); |
| + } |
| + |
| + private: |
| + ThreadLocalBoolean* scoped_tlb_; |
| + bool original_value_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ThreadLocalBooleanAutoReset); |
| +}; |
| + |
| +base::LazyInstance<ThreadLocalBoolean>::Leaky |
| + g_unchecked_malloc = LAZY_INSTANCE_INITIALIZER; |
| + |
| void CrMallocErrorBreak() { |
| g_original_malloc_error_break(); |
| // Out of memory is certainly not heap corruption, and not necessarily |
| // something for which the process should be terminated. Leave that decision |
| // to the OOM killer. |
| - if (errno == ENOMEM) |
| + if (errno == ENOMEM || (errno == EBADF && g_unchecked_malloc.Get().Get())) |
| return; |
| // A unit test checks this error message, so it needs to be in release builds. |
| - LOG(ERROR) << |
| + PLOG(ERROR) << |
| "Terminating process due to a potential for future heap corruption"; |
| - int* volatile death_ptr = NULL; |
| - *death_ptr = 0xf00bad; |
| + char* volatile death_ptr = NULL; |
| + death_ptr += errno; |
|
Mark Mentovai
2012/09/19 20:12:33
Oh, so now you trust errno to not be corrupt?
Scott Hess - ex-Googler
2012/09/19 20:27:51
Done. Though at some point we kind of have to ass
Mark Mentovai
2012/09/19 20:34:06
shess wrote:
|
| + *death_ptr = '!'; |
| } |
| } // namespace |
| @@ -836,16 +860,13 @@ id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) |
| } // namespace |
| -malloc_zone_t* GetPurgeableZone() { |
| - // malloc_default_purgeable_zone only exists on >= 10.6. Use dlsym to grab it |
| - // at runtime because it may not be present in the SDK used for compilation. |
| - typedef malloc_zone_t* (*malloc_default_purgeable_zone_t)(void); |
| - malloc_default_purgeable_zone_t malloc_purgeable_zone = |
| - reinterpret_cast<malloc_default_purgeable_zone_t>( |
| - dlsym(RTLD_DEFAULT, "malloc_default_purgeable_zone")); |
| - if (malloc_purgeable_zone) |
| - return malloc_purgeable_zone(); |
| - return NULL; |
| +void* UncheckedMalloc(size_t size) { |
| + if (g_old_malloc) { |
| + ScopedClearErrno clear_errno; |
| + ThreadLocalBooleanAutoReset flag(g_unchecked_malloc.Pointer(), true); |
| + return g_old_malloc(malloc_default_zone(), size); |
| + } |
| + return malloc(size); |
| } |
| void EnableTerminationOnOutOfMemory() { |
| @@ -880,7 +901,7 @@ void EnableTerminationOnOutOfMemory() { |
| ChromeMallocZone* default_zone = |
| reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); |
| ChromeMallocZone* purgeable_zone = |
| - reinterpret_cast<ChromeMallocZone*>(GetPurgeableZone()); |
| + reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); |
| vm_address_t page_start_default = 0; |
| vm_address_t page_start_purgeable = 0; |