1
0
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:
Heikki Linnakangas
2026-10-10 01:00:30 +03:00
parent 5f36942fd3
commit 6873a138f7
3 changed files with 32 additions and 16 deletions

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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);