From b6a1a71520716a0b8f1c64c9513745d8d4f8ef8c Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 8 Oct 2026 12:22:07 +0300 Subject: [PATCH v2 1/2] 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, because WAL insertion happens in a critical section, and you cannot create a new memory context in a critical section.) Oversight in 9b5acad3f40f. Co-authored-by:: Bharath Rupireddy Discussion: https://postgr.es/m/ Backpatch-through: 19 --- src/backend/access/transam/xlog.c | 40 +++++++++++++++---------- src/backend/access/transam/xloginsert.c | 5 ++++ src/include/access/xlog.h | 3 ++ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index afbe068cd0a..63d214782da 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -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. diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c index c9aff944a2e..2195df85b10 100644 --- a/src/backend/access/transam/xloginsert.c +++ b/src/backend/access/transam/xloginsert.c @@ -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 } diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 7a590b7e1ea..2bf5714b51e 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -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); -- 2.47.3