git.postgresql.org Git - postgresql.git/commitdiff

git projects / postgresql.git / commitdiff
? search:
summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: a0b99fc)
Move named LWLock tranche requests to shared memory.
2025年9月11日 21:13:55 +0000 (16:13 -0500)
2025年9月11日 21:13:55 +0000 (16:13 -0500)
In EXEC_BACKEND builds, GetNamedLWLockTranche() can segfault when
called outside of the postmaster process, as it might access
NamedLWLockTrancheRequestArray, which won't be initialized. Given
the lack of reports, this is apparently unusual, presumably because
it is usually called from a shmem_startup_hook like this:

mystruct = ShmemInitStruct(..., &found);
if (!found)
{
mystruct->locks = GetNamedLWLockTranche(...);
...
}

This genre of shmem_startup_hook evades the aforementioned
segfaults because the struct is initialized in the postmaster, so
all other callers skip the !found path.

We considered modifying the documentation or requiring
GetNamedLWLockTranche() to be called from the postmaster, but
ultimately we decided to simply move the request array to shared
memory (and add it to the BackendParameters struct), thereby
allowing calls outside postmaster on all platforms. Since the main
shared memory segment is initialized after accepting LWLock tranche
requests, postmaster builds the request array in local memory first
and then copies it to shared memory later.

Given the lack of reports, back-patching seems unnecessary.

Reported-by: Sami Imseih <samimseih@gmail.com>
Reviewed-by: Sami Imseih <samimseih@gmail.com>
Discussion: https://postgr.es/m/CAA5RZ0v1_15QPg5Sqd2Qz5rh_qcsyCeHHmRDY89xVHcy2yt5BQ%40mail.gmail.com


diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c
index a38979c50e4bbf3da3929117e1f8483eca40fb83..c5ef14e1eaae8dabc525bf7eee78643814ec9444 100644 (file)
--- 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 fcbac5213a5c045f609a54bd9b062932f799cca4..46c82c63ca5377b5066e12b5aa9d5b1abba9fcfe 100644 (file)
--- 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 0e9cf81a4c7668dcda82d621d2e372b06d082150..8e0d0d233b48ffdfaedd79f7a2bfbbae8dd1c88a 100644 (file)
--- 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;
/*
This is the main PostgreSQL git repository.
RSS Atom

AltStyle によって変換されたページ (->オリジナル) /