In nearly all cases of calling VIR_ALLOC*, VIR_REALLOC_N,
VIR_EXPAND_N, VIR_RESIZE_N, VIR_*_ELEMENT etc. we want to
report OOM error, so our source code base is full of:
if (VIR_ALLOC(somePtr) < 0) {
virReportOOMError();
goto cleanup;
}
or similar. Moreover, for those few cases where we don't want to
report OOM error (e.g. virReportOOMError() itself) a new
VIR_ALLOC_NOOOM macro is being introduced.
---
src/util/viralloc.c | 23 ++++++++++++++++++-----
src/util/viralloc.h | 13 ++++++++-----
src/util/virerror.c | 2 +-
3 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/src/util/viralloc.c b/src/util/viralloc.c
index 342b0eb..60c33d2 100644
--- a/src/util/viralloc.c
+++ b/src/util/viralloc.c
@@ -24,8 +24,11 @@
#include <stdlib.h>
#include "viralloc.h"
+#include "virerror.h"
#include "virlog.h"
+#define VIR_FROM_THIS VIR_FROM_NONE
+
#if TEST_OOM
static int testMallocNext = 0;
static int testMallocFailFirst = 0;
@@ -105,6 +108,7 @@ void virAllocTestHook(void (*func)(int, void*) ATTRIBUTE_UNUSED,
* virAlloc:
* @ptrptr: pointer to pointer for address of allocated memory
* @size: number of bytes to allocate
+ * @report: report OOM error
*
* Allocate 'size' bytes of memory. Return the address of the
* allocated memory in 'ptrptr'. The newly allocated memory is
@@ -112,7 +116,7 @@ void virAllocTestHook(void (*func)(int, void*) ATTRIBUTE_UNUSED,
*
* Returns -1 on failure to allocate, zero on success
*/
-int virAlloc(void *ptrptr, size_t size)
+int virAlloc(void *ptrptr, size_t size, bool report)
{
#if TEST_OOM
if (virAllocTestFail()) {
@@ -122,8 +126,11 @@ int virAlloc(void *ptrptr, size_t size)
#endif
*(void **)ptrptr = calloc(1, size);
- if (*(void **)ptrptr == NULL)
+ if (*(void **)ptrptr == NULL) {
+ if (report)
+ virReportOOMError();
return -1;
+ }
return 0;
}
@@ -150,8 +157,10 @@ int virAllocN(void *ptrptr, size_t size, size_t count)
#endif
*(void**)ptrptr = calloc(count, size);
- if (*(void**)ptrptr == NULL)
+ if (*(void**)ptrptr == NULL) {
+ virReportOOMError();
return -1;
+ }
return 0;
}
@@ -182,8 +191,10 @@ int virReallocN(void *ptrptr, size_t size, size_t count)
return -1;
}
tmp = realloc(*(void**)ptrptr, size * count);
- if (!tmp && (size * count))
+ if (!tmp && (size * count)) {
+ virReportOOMError();
return -1;
+ }
*(void**)ptrptr = tmp;
return 0;
}
@@ -422,8 +433,10 @@ int virAllocVar(void *ptrptr, size_t struct_size, size_t
element_size, size_t co
alloc_size = struct_size + (element_size * count);
*(void **)ptrptr = calloc(1, alloc_size);
- if (*(void **)ptrptr == NULL)
+ if (*(void **)ptrptr == NULL) {
+ virReportOOMError();
return -1;
+ }
return 0;
}
diff --git a/src/util/viralloc.h b/src/util/viralloc.h
index 7be7f82..30ffe15 100644
--- a/src/util/viralloc.h
+++ b/src/util/viralloc.h
@@ -46,7 +46,7 @@
/* Don't call these directly - use the macros below */
-int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK
+int virAlloc(void *ptrptr, size_t size, bool report) ATTRIBUTE_RETURN_CHECK
ATTRIBUTE_NONNULL(1);
int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK
ATTRIBUTE_NONNULL(1);
@@ -76,13 +76,16 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1);
* VIR_ALLOC:
* @ptr: pointer to hold address of allocated memory
*
- * Allocate sizeof(*ptr) bytes of memory and store
- * the address of allocated memory in 'ptr'. Fill the
- * newly allocated memory with zeros.
+ * Allocate sizeof(*ptr) bytes of memory and store the
+ * address of allocated memory in 'ptr'. Fill the newly
+ * allocated memory with zeros. If there's a failure,
+ * OOM error is reported. The VIR_ALLOC_NOOOM macro
+ * behaves the same except the OOM error reporting.
*
* Returns -1 on failure, 0 on success
*/
-# define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr)))
+# define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr)), true)
+# define VIR_ALLOC_NOOOM(ptr) virAlloc(&(ptr), sizeof(*(ptr)), true)
/**
* VIR_ALLOC_N:
diff --git a/src/util/virerror.c b/src/util/virerror.c
index c30642a..c033129 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -204,7 +204,7 @@ virLastErrorObject(void)
virErrorPtr err;
err = virThreadLocalGet(&virLastErr);
if (!err) {
- if (VIR_ALLOC(err) < 0)
+ if (VIR_ALLOC_NOOOM(err) < 0)
return NULL;
if (virThreadLocalSet(&virLastErr, err) < 0)
VIR_FREE(err);
--
1.8.1.5