Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/process_util.h" | 5 #include "base/process_util.h" |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 #include <crt_externs.h> | 8 #include <crt_externs.h> |
| 9 #include <dlfcn.h> | 9 #include <dlfcn.h> |
| 10 #include <errno.h> | 10 #include <errno.h> |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 #include <string> | 28 #include <string> |
| 29 | 29 |
| 30 #include "base/debug/debugger.h" | 30 #include "base/debug/debugger.h" |
| 31 #include "base/eintr_wrapper.h" | 31 #include "base/eintr_wrapper.h" |
| 32 #include "base/file_util.h" | 32 #include "base/file_util.h" |
| 33 #include "base/hash_tables.h" | 33 #include "base/hash_tables.h" |
| 34 #include "base/lazy_instance.h" | 34 #include "base/lazy_instance.h" |
| 35 #include "base/logging.h" | 35 #include "base/logging.h" |
| 36 #include "base/mac/mac_util.h" | 36 #include "base/mac/mac_util.h" |
| 37 #include "base/mac/scoped_mach_port.h" | 37 #include "base/mac/scoped_mach_port.h" |
| 38 #include "base/safe_strerror_posix.h" | |
| 38 #include "base/string_util.h" | 39 #include "base/string_util.h" |
| 39 #include "base/sys_info.h" | 40 #include "base/sys_info.h" |
| 40 #include "base/threading/thread_local.h" | 41 #include "base/threading/thread_local.h" |
| 41 #include "third_party/apple_apsl/CFBase.h" | 42 #include "third_party/apple_apsl/CFBase.h" |
| 42 #include "third_party/apple_apsl/malloc.h" | 43 #include "third_party/apple_apsl/malloc.h" |
| 43 #include "third_party/mach_override/mach_override.h" | 44 #include "third_party/mach_override/mach_override.h" |
| 44 | 45 |
| 45 namespace base { | 46 namespace base { |
| 46 | 47 |
| 47 void RestoreDefaultExceptionHandler() { | 48 void RestoreDefaultExceptionHandler() { |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 583 private: | 584 private: |
| 584 ThreadLocalBoolean* scoped_tlb_; | 585 ThreadLocalBoolean* scoped_tlb_; |
| 585 bool original_value_; | 586 bool original_value_; |
| 586 | 587 |
| 587 DISALLOW_COPY_AND_ASSIGN(ThreadLocalBooleanAutoReset); | 588 DISALLOW_COPY_AND_ASSIGN(ThreadLocalBooleanAutoReset); |
| 588 }; | 589 }; |
| 589 | 590 |
| 590 base::LazyInstance<ThreadLocalBoolean>::Leaky | 591 base::LazyInstance<ThreadLocalBoolean>::Leaky |
| 591 g_unchecked_malloc = LAZY_INSTANCE_INITIALIZER; | 592 g_unchecked_malloc = LAZY_INSTANCE_INITIALIZER; |
| 592 | 593 |
| 594 // NOTE(shess): This is called when the malloc library noticed that the heap | |
| 595 // is fubar. Avoid calls which will re-enter the malloc library. | |
| 593 void CrMallocErrorBreak() { | 596 void CrMallocErrorBreak() { |
| 594 g_original_malloc_error_break(); | 597 g_original_malloc_error_break(); |
| 595 | 598 |
| 596 // Out of memory is certainly not heap corruption, and not necessarily | 599 // Out of memory is certainly not heap corruption, and not necessarily |
| 597 // something for which the process should be terminated. Leave that decision | 600 // something for which the process should be terminated. Leave that decision |
| 598 // to the OOM killer. The EBADF case comes up because the malloc library | 601 // to the OOM killer. The EBADF case comes up because the malloc library |
| 599 // attempts to log to ASL (syslog) before calling this code, which fails | 602 // attempts to log to ASL (syslog) before calling this code, which fails |
| 600 // accessing a Unix-domain socket because of sandboxing. | 603 // accessing a Unix-domain socket because of sandboxing. |
| 601 if (errno == ENOMEM || (errno == EBADF && g_unchecked_malloc.Get().Get())) | 604 if (errno == ENOMEM || (errno == EBADF && g_unchecked_malloc.Get().Get())) |
| 602 return; | 605 return; |
| 603 | 606 |
| 604 // A unit test checks this error message, so it needs to be in release builds. | 607 // A unit test checks this error message, so it needs to be in release builds. |
| 605 PLOG(ERROR) << | 608 char buf[1024] = |
| 606 "Terminating process due to a potential for future heap corruption"; | 609 "Terminating process due to a potential for future heap corruption: "; |
| 610 size_t bl = strlen(buf); | |
|
Robert Sesek
2012/11/12 22:17:13
naming: |bl| -> |bufLen| ?
Scott Hess - ex-Googler
2012/11/12 22:31:52
Done.
| |
| 611 safe_strerror_r(errno, buf + bl, sizeof(buf) - bl); | |
| 612 RAW_LOG(ERROR, buf); | |
| 607 | 613 |
| 608 // Crash by writing to NULL+errno to allow analyzing errno from | 614 // Crash by writing to NULL+errno to allow analyzing errno from |
| 609 // crash dump info (setting a breakpad key would re-enter the malloc | 615 // crash dump info (setting a breakpad key would re-enter the malloc |
| 610 // library). Max documented errno in intro(2) is actually 102, but | 616 // library). Max documented errno in intro(2) is actually 102, but |
| 611 // it really just needs to be "small" to stay on the right vm page. | 617 // it really just needs to be "small" to stay on the right vm page. |
| 612 const int kMaxErrno = 256; | 618 const int kMaxErrno = 256; |
| 613 char* volatile death_ptr = NULL; | 619 char* volatile death_ptr = NULL; |
| 614 death_ptr += std::min(errno, kMaxErrno); | 620 death_ptr += std::min(errno, kMaxErrno); |
| 615 *death_ptr = '!'; | 621 *death_ptr = '!'; |
| 616 } | 622 } |
| 617 | 623 |
| 618 } // namespace | 624 } // namespace |
| 619 | 625 |
| 620 void EnableTerminationOnHeapCorruption() { | 626 void EnableTerminationOnHeapCorruption() { |
| 621 #ifdef ADDRESS_SANITIZER | 627 #ifdef ADDRESS_SANITIZER |
| 622 // Don't do anything special on heap corruption, because it should be handled | 628 // Don't do anything special on heap corruption, because it should be handled |
| 623 // by AddressSanitizer. | 629 // by AddressSanitizer. |
| 624 return; | 630 return; |
| 625 #endif | 631 #endif |
| 626 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); | 632 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); |
| 627 if (!malloc_error_break) { | 633 if (!malloc_error_break) { |
| 628 DLOG(WARNING) << "Could not find malloc_error_break"; | 634 DLOG(WARNING) << "Could not find malloc_error_break"; |
| 629 return; | 635 return; |
| 630 } | 636 } |
| 631 | 637 |
| 638 // Warm this up so that it doesn't require allocation when | |
| 639 // |CrMallocErrorBreak()| calls it. | |
| 640 ignore_result(g_unchecked_malloc.Get().Get()); | |
| 641 | |
| 632 mach_error_t err = mach_override_ptr( | 642 mach_error_t err = mach_override_ptr( |
| 633 (void*)malloc_error_break, | 643 (void*)malloc_error_break, |
| 634 (void*)&CrMallocErrorBreak, | 644 (void*)&CrMallocErrorBreak, |
| 635 (void**)&g_original_malloc_error_break); | 645 (void**)&g_original_malloc_error_break); |
| 636 | 646 |
| 637 if (err != err_none) | 647 if (err != err_none) |
| 638 DLOG(WARNING) << "Could not override malloc_error_break; error = " << err; | 648 DLOG(WARNING) << "Could not override malloc_error_break; error = " << err; |
| 639 } | 649 } |
| 640 | 650 |
| 641 // ------------------------------------------------------------------------ | 651 // ------------------------------------------------------------------------ |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1238 } | 1248 } |
| 1239 } | 1249 } |
| 1240 | 1250 |
| 1241 } // namespace | 1251 } // namespace |
| 1242 | 1252 |
| 1243 void EnsureProcessTerminated(ProcessHandle process) { | 1253 void EnsureProcessTerminated(ProcessHandle process) { |
| 1244 WaitForChildToDie(process, kWaitBeforeKillSeconds); | 1254 WaitForChildToDie(process, kWaitBeforeKillSeconds); |
| 1245 } | 1255 } |
| 1246 | 1256 |
| 1247 } // namespace base | 1257 } // namespace base |
| OLD | NEW |