This patch adds extra code to src/memory.c which allows us to force an OOM
condition on specific allocations. This is not code you *ever* want to use
in a production build, so its all conditional on TEST_OOM, which is enabled
by passing --enable-test-oom to the configure script.
The hooks work as follows...
- The test suite first calls virAllocTestInit() to initialize the hooks.
This causes it to start counting allocations.
....then run the code you want to check for OOM...
- Next call virAllocTestCount() to find out how many allocations were
made.
- Given a number of allocations 'n', we need to repeat 'n' times...
- Call virAllocTestOOM(n, m) to tell it to fail the n'th allocation
upto the (n + m -1)'th allocation. eg, virAllocTestOOM(3, 2)
will cause allocations 3 and 4 to fail.
... run the code you want to check and verify it reports OOM
in the way you expect.
It can be quite hard to find out just where allocation failure bugs are
hiding. So there is also a virAllocTestHook() function which lets you
register a callback to be invoked at the time an allocation is artificially
failed. Obvious use for this is to capture a stack trace.
configure.in | 29 +++++++++++++++++++++--
src/memory.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
src/memory.h | 11 +++++++-
3 files changed, 109 insertions(+), 5 deletions(-)
Regards,
Daniel
diff -r 9f962ac84b09 configure.in
--- a/configure.in Wed May 21 19:42:55 2008 -0400
+++ b/configure.in Wed May 21 22:22:47 2008 -0400
@@ -883,19 +883,39 @@
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])
AC_SUBST([COVERAGE_LDFLAGS], [$COMPILER_FLAGS])
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([HAVE_TRACE], 1, [Whether backtrace() is available])
+ fi
+ AC_DEFINE([TEST_OOM], 1, [Whether malloc OOM checking is enabled])
fi
dnl Enable building the proxy?
@@ -1042,6 +1062,11 @@
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 -r 9f962ac84b09 src/memory.c
--- a/src/memory.c Wed May 21 19:42:55 2008 -0400
+++ b/src/memory.c Wed May 21 22:22:47 2008 -0400
@@ -26,6 +26,59 @@
#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;
+
+ //printf("Alloc %d %d in [%d-%d]\n", fail, testMallocNext,
testMallocFailFirst, 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,12 +108,17 @@
*/
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)
@@ -83,6 +141,13 @@
*/
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 +176,11 @@
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 -r 9f962ac84b09 src/memory.h
--- a/src/memory.h Wed May 21 19:42:55 2008 -0400
+++ b/src/memory.h Wed May 21 22:22:47 2008 -0400
@@ -30,7 +30,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:
@@ -79,4 +78,14 @@
*/
#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_ */
--
|: Red Hat, Engineering, Boston -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|