From a45a1283e90487f22cf827833fb855ae7f07b113 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 23 Jun 2011 11:43:33 +0100 Subject: [PATCH 2/2] dbus-memory: add optional checking for system malloc() (etc.) failing If tests are enabled and DBUS_MALLOC_CANNOT_FAIL is set, abort on system malloc() failures (as GLib's g_malloc does). This can be used in conjunction with a resource limit, to turn runaway memory leaks into a debuggable core-dump. --- dbus/dbus-memory.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 77 insertions(+), 10 deletions(-) diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c index 16f54a6..5c8c73c 100644 --- a/dbus/dbus-memory.c +++ b/dbus/dbus-memory.c @@ -106,6 +106,7 @@ static int n_failures_this_failure = 0; static dbus_bool_t guards = FALSE; static dbus_bool_t disable_mem_pools = FALSE; static dbus_bool_t backtrace_on_fail_alloc = FALSE; +static dbus_bool_t malloc_cannot_fail = FALSE; static DBusAtomic n_blocks_outstanding = {0}; /** value stored in guard padding for debugging buffer overrun */ @@ -132,7 +133,7 @@ _dbus_initialize_malloc_debug (void) { fail_nth = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH")); fail_alloc_counter = fail_nth; - _dbus_verbose ("Will fail malloc every %d times\n", fail_nth); + _dbus_verbose ("Will fail dbus_malloc every %d times\n", fail_nth); } if (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN") != NULL) @@ -145,7 +146,7 @@ _dbus_initialize_malloc_debug (void) if (_dbus_getenv ("DBUS_MALLOC_GUARDS") != NULL) { guards = TRUE; - _dbus_verbose ("Will use malloc guards\n"); + _dbus_verbose ("Will use dbus_malloc guards\n"); } if (_dbus_getenv ("DBUS_DISABLE_MEM_POOLS") != NULL) @@ -157,7 +158,13 @@ _dbus_initialize_malloc_debug (void) if (_dbus_getenv ("DBUS_MALLOC_BACKTRACES") != NULL) { backtrace_on_fail_alloc = TRUE; - _dbus_verbose ("Will backtrace on failing a malloc\n"); + _dbus_verbose ("Will backtrace on failing a dbus_malloc\n"); + } + + if (_dbus_getenv ("DBUS_MALLOC_CANNOT_FAIL") != NULL) + { + malloc_cannot_fail = TRUE; + _dbus_verbose ("Will abort if system malloc() and friends fail\n"); } } } @@ -472,7 +479,15 @@ dbus_malloc (size_t bytes) block = malloc (bytes + GUARD_EXTRA_SIZE); if (block) - _dbus_atomic_inc (&n_blocks_outstanding); + { + _dbus_atomic_inc (&n_blocks_outstanding); + } + else if (malloc_cannot_fail) + { + _dbus_warn ("out of memory: malloc (%ld + %ld)\n", + (long) bytes, (long) GUARD_EXTRA_SIZE); + _dbus_abort (); + } return set_guards (block, bytes, SOURCE_MALLOC); } @@ -481,10 +496,19 @@ dbus_malloc (size_t bytes) { void *mem; mem = malloc (bytes); + #ifdef DBUS_BUILD_TESTS if (mem) - _dbus_atomic_inc (&n_blocks_outstanding); + { + _dbus_atomic_inc (&n_blocks_outstanding); + } + else if (malloc_cannot_fail) + { + _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes); + _dbus_abort (); + } #endif + return mem; } } @@ -525,8 +549,18 @@ dbus_malloc0 (size_t bytes) void *block; block = calloc (bytes + GUARD_EXTRA_SIZE, 1); + if (block) - _dbus_atomic_inc (&n_blocks_outstanding); + { + _dbus_atomic_inc (&n_blocks_outstanding); + } + else if (malloc_cannot_fail) + { + _dbus_warn ("out of memory: calloc (%ld + %ld, 1)\n", + (long) bytes, (long) GUARD_EXTRA_SIZE); + _dbus_abort (); + } + return set_guards (block, bytes, SOURCE_MALLOC_ZERO); } #endif @@ -534,10 +568,19 @@ dbus_malloc0 (size_t bytes) { void *mem; mem = calloc (bytes, 1); + #ifdef DBUS_BUILD_TESTS if (mem) - _dbus_atomic_inc (&n_blocks_outstanding); + { + _dbus_atomic_inc (&n_blocks_outstanding); + } + else if (malloc_cannot_fail) + { + _dbus_warn ("out of memory: calloc (%ld)\n", (long) bytes); + _dbus_abort (); + } #endif + return mem; } } @@ -588,7 +631,16 @@ dbus_realloc (void *memory, bytes + GUARD_EXTRA_SIZE); if (block == NULL) - return NULL; + { + if (malloc_cannot_fail) + { + _dbus_warn ("out of memory: realloc (%p, %ld + %ld)\n", + memory, (long) bytes, (long) GUARD_EXTRA_SIZE); + _dbus_abort (); + } + + return NULL; + } old_bytes = *(dbus_uint32_t*)block; if (bytes >= old_bytes) @@ -604,8 +656,16 @@ dbus_realloc (void *memory, block = malloc (bytes + GUARD_EXTRA_SIZE); if (block) - _dbus_atomic_inc (&n_blocks_outstanding); - + { + _dbus_atomic_inc (&n_blocks_outstanding); + } + else if (malloc_cannot_fail) + { + _dbus_warn ("out of memory: malloc (%ld + %ld)\n", + (long) bytes, (long) GUARD_EXTRA_SIZE); + _dbus_abort (); + } + return set_guards (block, bytes, SOURCE_REALLOC_NULL); } } @@ -614,7 +674,14 @@ dbus_realloc (void *memory, { void *mem; mem = realloc (memory, bytes); + #ifdef DBUS_BUILD_TESTS + if (mem == NULL && malloc_cannot_fail) + { + _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes); + _dbus_abort (); + } + if (memory == NULL && mem != NULL) _dbus_atomic_inc (&n_blocks_outstanding); #endif -- 1.7.6.3