On Mon, Sep 08, 2025 at 11:55:14AM -0500, Nathan Bossart wrote:
> I've started preparing this for commit, and I realized that restricting
> GetNamedLWLockTranche() to shmem_startup_hook is not sufficient.
> EXEC_BACKEND builds will run this hook in every backend, so unless it's
> guarded behind some sort of "if (!found)" condition (i.e., only run in the
> postmaster), it'll still crash.  I think we just need to add some extra
> notes to the docs and check for !IsUnderPostmaster, as discussed upthread.

Or... what if we just moved the request array to shared memory?

-- 
nathan
>From 5abfc98ef5dd26e2f3c822cbe51c6038fb4e37bf Mon Sep 17 00:00:00 2001
From: Nathan Bossart <[email protected]>
Date: Mon, 8 Sep 2025 13:18:59 -0500
Subject: [PATCH v3 1/1] Move named LWLock tranche request array to shared
 memory.

---
 src/backend/postmaster/launch_backend.c |  3 +++
 src/backend/storage/lmgr/lwlock.c       | 31 +++++++++++++++++++++----
 src/include/storage/lwlock.h            |  4 ++++
 3 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/src/backend/postmaster/launch_backend.c 
b/src/backend/postmaster/launch_backend.c
index a38979c50e4..c5ef14e1eaa 100644
--- a/src/backend/postmaster/launch_backend.c
+++ b/src/backend/postmaster/launch_backend.c
@@ -101,6 +101,7 @@ typedef struct
        struct InjectionPointsCtl *ActiveInjectionPoints;
 #endif
        int                     NamedLWLockTrancheRequests;
+       NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray;
        char      **LWLockTrancheNames;
        int                *LWLockCounter;
        LWLockPadded *MainLWLockArray;
@@ -761,6 +762,7 @@ save_backend_variables(BackendParameters *param,
 #endif
 
        param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests;
+       param->NamedLWLockTrancheRequestArray = NamedLWLockTrancheRequestArray;
        param->LWLockTrancheNames = LWLockTrancheNames;
        param->LWLockCounter = LWLockCounter;
        param->MainLWLockArray = MainLWLockArray;
@@ -1022,6 +1024,7 @@ restore_backend_variables(BackendParameters *param)
 #endif
 
        NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
+       NamedLWLockTrancheRequestArray = param->NamedLWLockTrancheRequestArray;
        LWLockTrancheNames = param->LWLockTrancheNames;
        LWLockCounter = param->LWLockCounter;
        MainLWLockArray = param->MainLWLockArray;
diff --git a/src/backend/storage/lmgr/lwlock.c 
b/src/backend/storage/lmgr/lwlock.c
index fcbac5213a5..46c82c63ca5 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -184,14 +184,13 @@ typedef struct NamedLWLockTrancheRequest
        int                     num_lwlocks;
 } NamedLWLockTrancheRequest;
 
-static NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray = NULL;
-
 /*
- * NamedLWLockTrancheRequests is the valid length of the request array.  This
- * variable is non-static so that postmaster.c can copy them to child processes
- * in EXEC_BACKEND builds.
+ * NamedLWLockTrancheRequests is the valid length of the request array.  These
+ * variables are non-static so that launch_backend.c can copy them to child
+ * processes in EXEC_BACKEND builds.
  */
 int                    NamedLWLockTrancheRequests = 0;
+NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray = NULL;
 
 /* shared memory counter of registered tranches */
 int               *LWLockCounter = NULL;
@@ -407,6 +406,14 @@ LWLockShmemSize(void)
        size = add_size(size, mul_size(MAX_NAMED_TRANCHES, sizeof(char *)));
        size = add_size(size, mul_size(MAX_NAMED_TRANCHES, NAMEDATALEN));
 
+       /*
+        * Make space for named tranche requests.  This is done for the benefit 
of
+        * EXEC_BACKEND builds, which otherwise wouldn't be able to call
+        * GetNamedLWLockTranche() outside postmaster.
+        */
+       size = add_size(size, mul_size(NamedLWLockTrancheRequests,
+                                                                  
sizeof(NamedLWLockTrancheRequest)));
+
        /* Space for the LWLock array, plus room for cache line alignment. */
        size = add_size(size, LWLOCK_PADDED_SIZE);
        size = add_size(size, mul_size(numLocks, sizeof(LWLockPadded)));
@@ -443,6 +450,20 @@ CreateLWLocks(void)
                        ptr += NAMEDATALEN;
                }
 
+               /*
+                * Move named tranche requests to shared memory.  This is done 
for the
+                * benefit of EXEC_BACKEND builds, which otherwise wouldn't be 
able to
+                * call GetNamedLWLockTranche() outside postmaster.
+                */
+               if (NamedLWLockTrancheRequests > 0)
+               {
+                       memcpy(ptr, NamedLWLockTrancheRequestArray,
+                                  NamedLWLockTrancheRequests * 
sizeof(NamedLWLockTrancheRequest));
+                       pfree(NamedLWLockTrancheRequestArray);
+                       NamedLWLockTrancheRequestArray = 
(NamedLWLockTrancheRequest *) ptr;
+                       ptr += NamedLWLockTrancheRequests * 
sizeof(NamedLWLockTrancheRequest);
+               }
+
                /* Ensure desired alignment of LWLock array */
                ptr += LWLOCK_PADDED_SIZE - ((uintptr_t) ptr) % 
LWLOCK_PADDED_SIZE;
                MainLWLockArray = (LWLockPadded *) ptr;
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 0e9cf81a4c7..8e0d0d233b4 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -73,8 +73,12 @@ typedef union LWLockPadded
 
 extern PGDLLIMPORT LWLockPadded *MainLWLockArray;
 
+/* forward declaration of private type for use only by lwlock.c */
+typedef struct NamedLWLockTrancheRequest NamedLWLockTrancheRequest;
+
 extern PGDLLIMPORT char **LWLockTrancheNames;
 extern PGDLLIMPORT int NamedLWLockTrancheRequests;
+extern PGDLLIMPORT NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray;
 extern PGDLLIMPORT int *LWLockCounter;
 
 /*
-- 
2.39.5 (Apple Git-154)

Reply via email to