Index: base/process_util_linux.cc |
=================================================================== |
--- base/process_util_linux.cc (revision 32206) |
+++ base/process_util_linux.cc (working copy) |
@@ -6,6 +6,7 @@ |
#include <ctype.h> |
#include <dirent.h> |
+#include <dlfcn.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <sys/time.h> |
@@ -497,8 +498,105 @@ |
return result_in_kb; |
} |
+namespace { |
+ |
+void OnNoMemorySize(size_t size) { |
+ if (size != 0) |
+ CHECK(false) << "Out of memory, size = " << size; |
+ CHECK(false) << "Out of memory."; |
+} |
+ |
+void OnNoMemory() { |
+ OnNoMemorySize(0); |
+} |
+ |
+} // namespace |
+ |
+extern "C" { |
+ |
+#if defined(LINUX_USE_TCMALLOC) |
+ |
+int tc_set_new_mode(int mode); |
+ |
+#else // defined(LINUX_USE_TCMALLOC) |
+ |
+typedef void* (*malloc_type)(size_t size); |
+typedef void* (*valloc_type)(size_t size); |
+typedef void* (*pvalloc_type)(size_t size); |
+ |
+typedef void* (*calloc_type)(size_t nmemb, size_t size); |
+typedef void* (*realloc_type)(void *ptr, size_t size); |
+typedef void* (*memalign_type)(size_t boundary, size_t size); |
+ |
+typedef int (*posix_memalign_type)(void **memptr, size_t alignment, |
+ size_t size); |
+ |
+// Override the __libc_FOO name too. |
+#define DIE_ON_OOM_1(function_name) \ |
+ _DIE_ON_OOM_1(function_name##_type, function_name) \ |
+ _DIE_ON_OOM_1(function_name##_type, __libc_##function_name) |
+ |
+#define DIE_ON_OOM_2(function_name, arg1_type) \ |
+ _DIE_ON_OOM_2(function_name##_type, function_name, arg1_type) \ |
+ _DIE_ON_OOM_2(function_name##_type, __libc_##function_name, arg1_type) |
+ |
+// posix_memalign doesn't have a __libc_ variant. |
+#define DIE_ON_OOM_3INT(function_name) \ |
+ _DIE_ON_OOM_3INT(function_name##_type, function_name) |
+ |
+#define _DIE_ON_OOM_1(function_type, function_name) \ |
+ void* function_name(size_t size) { \ |
+ static function_type original_function = \ |
+ reinterpret_cast<function_type>(dlsym(RTLD_NEXT, #function_name)); \ |
+ void* ret = original_function(size); \ |
+ if (ret == NULL && size != 0) \ |
+ OnNoMemorySize(size); \ |
+ return ret; \ |
+ } |
+ |
+#define _DIE_ON_OOM_2(function_type, function_name, arg1_type) \ |
+ void* function_name(arg1_type arg1, size_t size) { \ |
+ static function_type original_function = \ |
+ reinterpret_cast<function_type>(dlsym(RTLD_NEXT, #function_name)); \ |
+ void* ret = original_function(arg1, size); \ |
+ if (ret == NULL && size != 0) \ |
+ OnNoMemorySize(size); \ |
+ return ret; \ |
+ } |
+ |
+#define _DIE_ON_OOM_3INT(function_type, function_name) \ |
+ int function_name(void** ptr, size_t alignment, size_t size) { \ |
+ static function_type original_function = \ |
+ reinterpret_cast<function_type>(dlsym(RTLD_NEXT, #function_name)); \ |
+ int ret = original_function(ptr, alignment, size); \ |
+ if (ret == ENOMEM) \ |
+ OnNoMemorySize(size); \ |
+ return ret; \ |
+ } |
+ |
+DIE_ON_OOM_1(malloc) |
+DIE_ON_OOM_1(valloc) |
+DIE_ON_OOM_1(pvalloc) |
+ |
+DIE_ON_OOM_2(calloc, size_t) |
+DIE_ON_OOM_2(realloc, void*) |
+DIE_ON_OOM_2(memalign, size_t) |
+ |
+DIE_ON_OOM_3INT(posix_memalign) |
+ |
+#endif // defined(LINUX_USE_TCMALLOC) |
+ |
+} // extern C |
+ |
void EnableTerminationOnOutOfMemory() { |
- // http://crbug.com/27222 |
+ // Set the new-out of memory handler. |
+ std::set_new_handler(&OnNoMemory); |
+ // If we're using glibc's allocator, the above functions will override |
+ // malloc and friends and make them die on out of memory. |
+#if defined(LINUX_USE_TCMALLOC) |
+ // For tcmalloc, we just need to tell it to behave like new. |
+ tc_set_new_mode(1); |
+#endif |
} |
} // namespace base |