mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Fix crash with wal_debug in EXEC_BACKEND child processes
Converting xlog.c to the new shared memory allocation API left the
creation of the memory context used by wal_debug in the
XLOGShmemInit() callback, which now only runs in the postmaster or in
a standalone backend. Previously, XLOGShmemInit() ran in every child.
As a result, walDebugCtx was left uninitialized in child processes in
EXEC_BACKEND mode, and with wal_debug turned on, the backend crashed
on first WAL insertion.
Fix by moving the walDebugCtx initialization to a separate function
that is called in each backend that wishes to create WAL records. (It
cannot be created lazily on first WAL insertion, because it's done in
a critical section, and you cannot create a new memory context in a
critical section.)
Oversight in 9b5acad3f4.
Co-authored-by:: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/CALj2ACUNL4Xn3aBzvm4DTpdr_L0-AfL2agsghMRRy_ZTiKhxSA@mail.gmail.com
Backpatch-through: 19
This commit is contained in:
@@ -5570,22 +5570,6 @@ XLOGShmemInit(void *arg)
|
||||
char *allocptr;
|
||||
int i;
|
||||
|
||||
#ifdef WAL_DEBUG
|
||||
|
||||
/*
|
||||
* Create a memory context for WAL debugging that's exempt from the normal
|
||||
* "no pallocs in critical section" rule. Yes, that can lead to a PANIC if
|
||||
* an allocation fails, but wal_debug is not for production use anyway.
|
||||
*/
|
||||
if (walDebugCxt == NULL)
|
||||
{
|
||||
walDebugCxt = AllocSetContextCreate(TopMemoryContext,
|
||||
"WAL Debug",
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
MemoryContextAllowInCriticalSection(walDebugCxt, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(XLogCtl, 0, sizeof(XLogCtlData));
|
||||
|
||||
/*
|
||||
@@ -5669,6 +5653,30 @@ XLOGShmemAttach(void *arg)
|
||||
WALInsertLocks = XLogCtl->Insert.WALInsertLocks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize process-local state needed by wal_debug.
|
||||
*
|
||||
* This must be called before XLogInsertRecord().
|
||||
*/
|
||||
#ifdef WAL_DEBUG
|
||||
void
|
||||
InitWalDebug(void)
|
||||
{
|
||||
/*
|
||||
* Create a memory context for WAL debugging that's exempt from the normal
|
||||
* "no pallocs in critical section" rule. Yes, that can lead to a PANIC if
|
||||
* an allocation fails, but wal_debug is not for production use anyway.
|
||||
*/
|
||||
if (walDebugCxt == NULL)
|
||||
{
|
||||
walDebugCxt = AllocSetContextCreate(TopMemoryContext,
|
||||
"WAL Debug",
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
MemoryContextAllowInCriticalSection(walDebugCxt, true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This func must be called ONCE on system install. It creates pg_control
|
||||
* and the initial XLOG segment.
|
||||
|
||||
@@ -1437,4 +1437,9 @@ InitXLogInsert(void)
|
||||
if (hdr_scratch == NULL)
|
||||
hdr_scratch = MemoryContextAllocZero(xloginsert_cxt,
|
||||
HEADER_SCRATCH_SIZE);
|
||||
|
||||
/* Extra initialization for wal_debug */
|
||||
#ifdef WAL_DEBUG
|
||||
InitWalDebug();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -234,6 +234,9 @@ extern bool XLogBackgroundFlush(void);
|
||||
extern bool XLogNeedsFlush(XLogRecPtr record);
|
||||
extern int XLogFileInit(XLogSegNo logsegno, TimeLineID logtli);
|
||||
extern int XLogFileOpen(XLogSegNo segno, TimeLineID tli);
|
||||
#ifdef WAL_DEBUG
|
||||
extern void InitWalDebug(void);
|
||||
#endif
|
||||
|
||||
extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);
|
||||
extern XLogSegNo XLogGetLastRemovedSegno(void);
|
||||
|
||||
Reference in New Issue
Block a user