On Wed, Sep 17, 2025 at 01:47:19PM +0900, Michael Paquier wrote: > Perhaps LocalNamedLWLockTrancheRequestArray should be initialized to > NULL when declared, and I'd rather document the reasons behind what > this patch is doing in LWLockShmemSize() and when the state is > initialized in CreateLWLocks(), than have the reader assume why the > local pointer is needed (aka reinitialized with restart_after_crash).
I've added some commentary to this effect in v3. > Note: I forgot for a second if shared_preload_libraries was reloaded > when the postmaster reinitializes a cluster, and the answer is that > we only go into process_shared_preload_libraries() once at startup.. > I was wondering for a second about a potential case where s_p_l is > updated with more lwlocks added in-between, where a reinitialization > would mess up things. Yeah, this stuff is rather precarious, and I'm a bit surprised there haven't been more problems in this area. -- nathan
>From 1fbbc7df0fb2979eaaecf11d0f7d8203e527ff0b Mon Sep 17 00:00:00 2001 From: Nathan Bossart <nat...@postgresql.org> Date: Wed, 17 Sep 2025 09:24:45 -0500 Subject: [PATCH v3 1/1] Fix re-initialization of LWLock-related shared memory. When shared memory is re-initialized after a crash, the named LWLock tranche request array that was copied to shared memory will no longer be accessible. To fix, save the pointer to the original array in postmaster's local memory, and switch to it when re-initializing the LWLock-related shared memory. Oversight in commit ed1aad15e0. Per buildfarm member batta. Reported-by: Michael Paquier <mich...@paquier.xyz> Reviewed-by: Michael Paquier <mich...@paquier.xyz> Discussion: https://postgr.es/m/E1uwodL-000EuJ-2j%40gemulon.postgresql.org --- src/backend/storage/lmgr/lwlock.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 46c82c63ca5..527bd85c1f7 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -192,6 +192,9 @@ typedef struct NamedLWLockTrancheRequest int NamedLWLockTrancheRequests = 0; NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray = NULL; +/* postmaster's local copy of the request array */ +static NamedLWLockTrancheRequest *LocalNamedLWLockTrancheRequestArray = NULL; + /* shared memory counter of registered tranches */ int *LWLockCounter = NULL; @@ -396,6 +399,15 @@ LWLockShmemSize(void) Size size; int numLocks = NUM_FIXED_LWLOCKS; + /* + * If re-initializing shared memory, the request array will no longer be + * accessible, so switch to the copy that was stowed away in postmaster's + * local memory. We'll copy it back into shared memory later when + * CreateLWLocks() is called again. + */ + if (LocalNamedLWLockTrancheRequestArray) + NamedLWLockTrancheRequestArray = LocalNamedLWLockTrancheRequestArray; + /* Calculate total number of locks needed in the main array. */ numLocks += NumLWLocksForNamedTranches(); @@ -457,9 +469,15 @@ CreateLWLocks(void) */ if (NamedLWLockTrancheRequests > 0) { + /* + * Save the pointer to the request array in postmaster's local + * memory. We'll need it if we ever need to re-initialize shared + * memory after a crash. + */ + LocalNamedLWLockTrancheRequestArray = NamedLWLockTrancheRequestArray; + memcpy(ptr, NamedLWLockTrancheRequestArray, NamedLWLockTrancheRequests * sizeof(NamedLWLockTrancheRequest)); - pfree(NamedLWLockTrancheRequestArray); NamedLWLockTrancheRequestArray = (NamedLWLockTrancheRequest *) ptr; ptr += NamedLWLockTrancheRequests * sizeof(NamedLWLockTrancheRequest); } -- 2.39.5 (Apple Git-154)