From 18da6991e16a80fd2e41367add9789b94ceaef13 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 29 May 2008 15:13:07 +0000 Subject: [PATCH] Generic OOM testing hooks --- ChangeLog | 5 ++++ configure.in | 29 +++++++++++++++++++-- src/memory.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/memory.h | 11 +++++++- 4 files changed, 112 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50505ae84f..080e32fb89 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu May 29 11:12:00 EST 2008 Daniel P. Berrange + + * src/memory.c, src/memory.h, configure.ac: Add generics hooks + for out-of-memory testing + Thu May 29 10:55:00 EST 2008 Daniel P. Berrange * src/virsh.c: Don't add trailing blanks in dominfo output diff --git a/configure.in b/configure.in index 8ba3cdce18..e8d3f065de 100644 --- a/configure.in +++ b/configure.in @@ -883,14 +883,15 @@ AC_MSG_RESULT($RUNNING_XEND) AM_CONDITIONAL([ENABLE_XEN_TESTS], [test "$RUNNING_XEN" != "no" -a "$RUNNING_XEND" != "no"]) AC_ARG_ENABLE([test-coverage], -[ --enable-test-coverage turn on code coverage instrumentation], +[ --enable-test-coverage turn on code coverage instrumentation], [case "${enableval}" in yes|no) ;; *) AC_MSG_ERROR([bad value ${enableval} for test-coverage option]) ;; esac], [enableval=no]) +enable_coverage=$enableval -if test "${enableval}" = yes; then +if test "${enable_coverage}" = yes; then gl_COMPILER_FLAGS(-fprofile-arcs) gl_COMPILER_FLAGS(-ftest-coverage) AC_SUBST([COVERAGE_CFLAGS], [$COMPILER_FLAGS]) @@ -898,6 +899,25 @@ if test "${enableval}" = yes; then COMPILER_FLAGS= fi +AC_ARG_ENABLE([test-oom], +[ --enable-test-oom memory allocation failure checking], +[case "${enableval}" in + yes|no) ;; + *) AC_MSG_ERROR([bad value ${enableval} for test-oom option]) ;; + esac], + [enableval=no]) +enable_oom=$enableval + +if test "${enable_oom}" = yes; then + have_trace=yes + AC_CHECK_HEADER([execinfo.h],[],[have_trace=no]) + AC_CHECK_FUNC([backtrace],[],[have_trace=no]) + if test "$have_trace" = "yes"; then + AC_DEFINE([TEST_OOM_TRACE], 1, [Whether backtrace() is available]) + fi + AC_DEFINE([TEST_OOM], 1, [Whether malloc OOM checking is enabled]) +fi + dnl Enable building the proxy? AC_ARG_WITH([xen-proxy], @@ -1042,6 +1062,11 @@ else AC_MSG_NOTICE([ numactl: no]) fi AC_MSG_NOTICE([]) +AC_MSG_NOTICE([Test suite]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Coverage: $enable_coverage]) +AC_MSG_NOTICE([ Alloc OOM: $enable_oom]) +AC_MSG_NOTICE([]) AC_MSG_NOTICE([Miscellaneous]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ Debug: $enable_debug]) diff --git a/src/memory.c b/src/memory.c index 1eb1be3c3d..5a55f2acd4 100644 --- a/src/memory.c +++ b/src/memory.c @@ -26,6 +26,57 @@ #include "memory.h" +#if TEST_OOM +static int testMallocNext = 0; +static int testMallocFailFirst = 0; +static int testMallocFailLast = 0; +static void (*testMallocHook)(void*) = NULL; +static void *testMallocHookData = NULL; + +void virAllocTestInit(void) +{ + testMallocNext = 1; + testMallocFailFirst = 0; + testMallocFailLast = 0; +} + +int virAllocTestCount(void) +{ + return testMallocNext - 1; +} + +void virAllocTestHook(void (*func)(void*), void *data) +{ + testMallocHook = func; + testMallocHookData = data; +} + +void virAllocTestOOM(int n, int m) +{ + testMallocNext = 1; + testMallocFailFirst = n; + testMallocFailLast = n + m - 1; +} + +static int virAllocTestFail(void) +{ + int fail = 0; + if (testMallocNext == 0) + return 0; + + fail = + testMallocNext >= testMallocFailFirst && + testMallocNext <= testMallocFailLast; + + if (fail && testMallocHook) + (testMallocHook)(testMallocHookData); + + testMallocNext++; + return fail; +} +#endif + + /* Return 1 if an array of N objects, each of size S, cannot exist due to size arithmetic overflow. S must be positive and N must be nonnegative. This is a macro, not an inline function, so that it @@ -55,13 +106,18 @@ */ int virAlloc(void *ptrptr, size_t size) { +#if TEST_OOM + if (virAllocTestFail()) { + *(void **)ptrptr = NULL; + return -1; + } +#endif + if (size == 0) { *(void **)ptrptr = NULL; return 0; } - - *(void **)ptrptr = calloc(1, size); if (*(void **)ptrptr == NULL) return -1; @@ -83,6 +139,13 @@ int virAlloc(void *ptrptr, size_t size) */ int virAllocN(void *ptrptr, size_t size, size_t count) { +#if TEST_OOM + if (virAllocTestFail()) { + *(void **)ptrptr = NULL; + return -1; + } +#endif + if (size == 0 || count == 0) { *(void **)ptrptr = NULL; return 0; @@ -111,6 +174,11 @@ int virAllocN(void *ptrptr, size_t size, size_t count) int virReallocN(void *ptrptr, size_t size, size_t count) { void *tmp; +#if TEST_OOM + if (virAllocTestFail()) + return -1; +#endif + if (size == 0 || count == 0) { free(*(void **)ptrptr); *(void **)ptrptr = NULL; diff --git a/src/memory.h b/src/memory.h index 872fd8cc7a..2331b11c11 100644 --- a/src/memory.h +++ b/src/memory.h @@ -31,7 +31,6 @@ int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK; int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK; void virFree(void *ptrptr); - /** * VIR_ALLOC: * @ptr: pointer to hold address of allocated memory @@ -79,4 +78,14 @@ void virFree(void *ptrptr); */ #define VIR_FREE(ptr) virFree(&(ptr)); + +#if TEST_OOM +void virAllocTestInit(void); +int virAllocTestCount(void); +void virAllocTestOOM(int n, int m); +void virAllocTestHook(void (*func)(void*), void *data); +#endif + + + #endif /* __VIR_MEMORY_H_ */