From 3d6d1b585524aab62616d20518fe1fe3be5d1a39 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Thu, 29 Jan 2015 10:23:38 -0500 Subject: [PATCH] Move out-of-memory error checks from aset.c to mcxt.c This potentially allows us to add mcxt.c interfaces that do something other than throw an error when memory cannot be allocated. We'll handle adding those interfaces in a separate commit. Michael Paquier, with minor changes by me --- src/backend/utils/mmgr/aset.c | 39 +++++++-------------- src/backend/utils/mmgr/mcxt.c | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 85b3c9acd1..0759e39ecb 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -642,8 +642,8 @@ AllocSetDelete(MemoryContext context) /* * AllocSetAlloc - * Returns pointer to allocated memory of given size; memory is added - * to the set. + * Returns pointer to allocated memory of given size or NULL if + * request could not be completed; memory is added to the set. * * No request may exceed: * MAXALIGN_DOWN(SIZE_MAX) - ALLOC_BLOCKHDRSZ - ALLOC_CHUNKHDRSZ @@ -671,13 +671,7 @@ AllocSetAlloc(MemoryContext context, Size size) blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ; block = (AllocBlock) malloc(blksize); if (block == NULL) - { - MemoryContextStats(TopMemoryContext); - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"), - errdetail("Failed on request of size %zu.", size))); - } + return NULL; block->aset = set; block->freeptr = block->endptr = ((char *) block) + blksize; @@ -865,13 +859,7 @@ AllocSetAlloc(MemoryContext context, Size size) } if (block == NULL) - { - MemoryContextStats(TopMemoryContext); - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"), - errdetail("Failed on request of size %zu.", size))); - } + return NULL; block->aset = set; block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ; @@ -1002,9 +990,10 @@ AllocSetFree(MemoryContext context, void *pointer) /* * AllocSetRealloc - * Returns new pointer to allocated memory of given size; this memory - * is added to the set. Memory associated with given pointer is copied - * into the new memory, and the old memory is freed. + * Returns new pointer to allocated memory of given size or NULL if + * request could not be completed; this memory is added to the set. + * Memory associated with given pointer is copied into the new memory, + * and the old memory is freed. * * Without MEMORY_CONTEXT_CHECKING, we don't know the old request size. This * makes our Valgrind client requests less-precise, hazarding false negatives. @@ -1107,13 +1096,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size) blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ; block = (AllocBlock) realloc(block, blksize); if (block == NULL) - { - MemoryContextStats(TopMemoryContext); - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"), - errdetail("Failed on request of size %zu.", size))); - } + return NULL; block->freeptr = block->endptr = ((char *) block) + blksize; /* Update pointers since block has likely been moved */ @@ -1179,6 +1162,10 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size) /* allocate new chunk */ newPointer = AllocSetAlloc((MemoryContext) set, size); + /* leave immediately if request was not completed */ + if (newPointer == NULL) + return NULL; + /* * AllocSetAlloc() just made the region NOACCESS. Change it to * UNDEFINED for the moment; memcpy() will then transfer definedness diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index aa0d458d25..c62922a187 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -623,6 +623,15 @@ MemoryContextAlloc(MemoryContext context, Size size) context->isReset = false; ret = (*context->methods->alloc) (context, size); + if (ret == NULL) + { + MemoryContextStats(TopMemoryContext); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %zu.", size))); + } + VALGRIND_MEMPOOL_ALLOC(context, ret, size); return ret; @@ -649,6 +658,15 @@ MemoryContextAllocZero(MemoryContext context, Size size) context->isReset = false; ret = (*context->methods->alloc) (context, size); + if (ret == NULL) + { + MemoryContextStats(TopMemoryContext); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %zu.", size))); + } + VALGRIND_MEMPOOL_ALLOC(context, ret, size); MemSetAligned(ret, 0, size); @@ -677,6 +695,15 @@ MemoryContextAllocZeroAligned(MemoryContext context, Size size) context->isReset = false; ret = (*context->methods->alloc) (context, size); + if (ret == NULL) + { + MemoryContextStats(TopMemoryContext); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %zu.", size))); + } + VALGRIND_MEMPOOL_ALLOC(context, ret, size); MemSetLoop(ret, 0, size); @@ -699,6 +726,15 @@ palloc(Size size) CurrentMemoryContext->isReset = false; ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size); + if (ret == NULL) + { + MemoryContextStats(TopMemoryContext); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %zu.", size))); + } + VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size); return ret; @@ -719,6 +755,15 @@ palloc0(Size size) CurrentMemoryContext->isReset = false; ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size); + if (ret == NULL) + { + MemoryContextStats(TopMemoryContext); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %zu.", size))); + } + VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size); MemSetAligned(ret, 0, size); @@ -789,6 +834,12 @@ repalloc(void *pointer, Size size) Assert(!context->isReset); ret = (*context->methods->realloc) (context, pointer, size); + if (ret == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %zu.", size))); + VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size); return ret; @@ -814,6 +865,15 @@ MemoryContextAllocHuge(MemoryContext context, Size size) context->isReset = false; ret = (*context->methods->alloc) (context, size); + if (ret == NULL) + { + MemoryContextStats(TopMemoryContext); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %zu.", size))); + } + VALGRIND_MEMPOOL_ALLOC(context, ret, size); return ret; @@ -854,6 +914,12 @@ repalloc_huge(void *pointer, Size size) Assert(!context->isReset); ret = (*context->methods->realloc) (context, pointer, size); + if (ret == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %zu.", size))); + VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size); return ret;