mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-28 01:11:50 +02:00
Add an Assertion that you don't palloc within a critical section.
This caught a bunch of cases doing that already, which I just fixed in previous commit. This is the assertion itself. Per Tom Lane's idea.
This commit is contained in:
parent
877b088785
commit
4a170ee9e0
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "miscadmin.h"
|
||||||
#include "utils/memdebug.h"
|
#include "utils/memdebug.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
|
|
||||||
@ -55,6 +56,19 @@ MemoryContext PortalContext = NULL;
|
|||||||
|
|
||||||
static void MemoryContextStatsInternal(MemoryContext context, int level);
|
static void MemoryContextStatsInternal(MemoryContext context, int level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You should not do memory allocations within a critical section, because
|
||||||
|
* an out-of-memory error will be escalated to a PANIC. To enforce that
|
||||||
|
* rule, the allocation functions Assert that.
|
||||||
|
*
|
||||||
|
* There are a two exceptions: 1) error recovery uses ErrorContext, which
|
||||||
|
* has some memory set aside so that you don't run out. And 2) checkpointer
|
||||||
|
* currently just hopes for the best, which is wrong and ought to be fixed,
|
||||||
|
* but it's a known issue so let's not complain about in the meanwhile.
|
||||||
|
*/
|
||||||
|
#define AssertNotInCriticalSection(context) \
|
||||||
|
Assert(CritSectionCount == 0 || (context) == ErrorContext || \
|
||||||
|
AmCheckpointerProcess())
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* EXPORTED ROUTINES *
|
* EXPORTED ROUTINES *
|
||||||
@ -519,6 +533,8 @@ MemoryContextCreate(NodeTag tag, Size size,
|
|||||||
MemoryContext node;
|
MemoryContext node;
|
||||||
Size needed = size + strlen(name) + 1;
|
Size needed = size + strlen(name) + 1;
|
||||||
|
|
||||||
|
Assert(CritSectionCount == 0);
|
||||||
|
|
||||||
/* Get space for node and name */
|
/* Get space for node and name */
|
||||||
if (TopMemoryContext != NULL)
|
if (TopMemoryContext != NULL)
|
||||||
{
|
{
|
||||||
@ -575,6 +591,7 @@ MemoryContextAlloc(MemoryContext context, Size size)
|
|||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
AssertArg(MemoryContextIsValid(context));
|
AssertArg(MemoryContextIsValid(context));
|
||||||
|
AssertNotInCriticalSection(context);
|
||||||
|
|
||||||
if (!AllocSizeIsValid(size))
|
if (!AllocSizeIsValid(size))
|
||||||
elog(ERROR, "invalid memory alloc request size %zu", size);
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
||||||
@ -600,6 +617,7 @@ MemoryContextAllocZero(MemoryContext context, Size size)
|
|||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
AssertArg(MemoryContextIsValid(context));
|
AssertArg(MemoryContextIsValid(context));
|
||||||
|
AssertNotInCriticalSection(context);
|
||||||
|
|
||||||
if (!AllocSizeIsValid(size))
|
if (!AllocSizeIsValid(size))
|
||||||
elog(ERROR, "invalid memory alloc request size %zu", size);
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
||||||
@ -627,6 +645,7 @@ MemoryContextAllocZeroAligned(MemoryContext context, Size size)
|
|||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
AssertArg(MemoryContextIsValid(context));
|
AssertArg(MemoryContextIsValid(context));
|
||||||
|
AssertNotInCriticalSection(context);
|
||||||
|
|
||||||
if (!AllocSizeIsValid(size))
|
if (!AllocSizeIsValid(size))
|
||||||
elog(ERROR, "invalid memory alloc request size %zu", size);
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
||||||
@ -648,6 +667,7 @@ palloc(Size size)
|
|||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
AssertArg(MemoryContextIsValid(CurrentMemoryContext));
|
AssertArg(MemoryContextIsValid(CurrentMemoryContext));
|
||||||
|
AssertNotInCriticalSection(CurrentMemoryContext);
|
||||||
|
|
||||||
if (!AllocSizeIsValid(size))
|
if (!AllocSizeIsValid(size))
|
||||||
elog(ERROR, "invalid memory alloc request size %zu", size);
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
||||||
@ -667,6 +687,7 @@ palloc0(Size size)
|
|||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
AssertArg(MemoryContextIsValid(CurrentMemoryContext));
|
AssertArg(MemoryContextIsValid(CurrentMemoryContext));
|
||||||
|
AssertNotInCriticalSection(CurrentMemoryContext);
|
||||||
|
|
||||||
if (!AllocSizeIsValid(size))
|
if (!AllocSizeIsValid(size))
|
||||||
elog(ERROR, "invalid memory alloc request size %zu", size);
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
||||||
@ -738,6 +759,7 @@ repalloc(void *pointer, Size size)
|
|||||||
((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
|
((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
|
||||||
|
|
||||||
AssertArg(MemoryContextIsValid(context));
|
AssertArg(MemoryContextIsValid(context));
|
||||||
|
AssertNotInCriticalSection(context);
|
||||||
|
|
||||||
/* isReset must be false already */
|
/* isReset must be false already */
|
||||||
Assert(!context->isReset);
|
Assert(!context->isReset);
|
||||||
@ -760,6 +782,7 @@ MemoryContextAllocHuge(MemoryContext context, Size size)
|
|||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
AssertArg(MemoryContextIsValid(context));
|
AssertArg(MemoryContextIsValid(context));
|
||||||
|
AssertNotInCriticalSection(context);
|
||||||
|
|
||||||
if (!AllocHugeSizeIsValid(size))
|
if (!AllocHugeSizeIsValid(size))
|
||||||
elog(ERROR, "invalid memory alloc request size %zu", size);
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
||||||
@ -801,6 +824,7 @@ repalloc_huge(void *pointer, Size size)
|
|||||||
((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
|
((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
|
||||||
|
|
||||||
AssertArg(MemoryContextIsValid(context));
|
AssertArg(MemoryContextIsValid(context));
|
||||||
|
AssertNotInCriticalSection(context);
|
||||||
|
|
||||||
/* isReset must be false already */
|
/* isReset must be false already */
|
||||||
Assert(!context->isReset);
|
Assert(!context->isReset);
|
||||||
|
Loading…
Reference in New Issue
Block a user