From 00bc0ef20633bffc066f850d1a553108cebcda4a Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 4 Sep 2025 21:08:56 +0000 Subject: [PATCH v2 1/1] Prevent crash when retreiving LWLock tranches GetNamedLWLockTranche() can crash if called outside shmem_startup_hook(). Under EXEC_BACKEND, there is no provision to copy the NamedLWLockTrancheRequestArray, whereas fork() automatically copies it for a normal backend. Moreover, there is no valid use case for calling GetNamedLWLockTranche() outside shmem_startup_hook(). To address this, shmem startup is centralized in process_shmem_startup(), with process_shmem_startup_in_progress indicating whether we are inside this hook. This enforces that GetNamedLWLockTranche() is only called during the startup hook. Update documentation to reflect this behavior. Discussion: https://www.postgresql.org/message-id/flat/CAA5RZ0v1_15QPg5Sqd2Qz5rh_qcsyCeHHmRDY89xVHcy2yt5BQ@mail.gmail.com --- doc/src/sgml/xfunc.sgml | 3 ++- src/backend/storage/ipc/ipci.c | 16 ++++++++++++---- src/backend/storage/lmgr/lwlock.c | 9 +++++++++ src/include/storage/ipc.h | 2 ++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index da21ef56891..774d21c8734 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -3743,7 +3743,8 @@ void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks) This ensures that an array of num_lwlocks LWLocks is available under the name tranche_name. A pointer to - this array can be obtained by calling: + this array can be obtained in the shmem_startup_hook + by calling: LWLockPadded *GetNamedLWLockTranche(const char *tranche_name) diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 2fa045e6b0f..786c5f258c6 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -56,6 +56,7 @@ int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE; shmem_startup_hook_type shmem_startup_hook = NULL; +bool process_shmem_startup_in_progress = false; static Size total_addin_request = 0; @@ -187,8 +188,7 @@ AttachSharedMemoryStructs(void) /* * Now give loadable modules a chance to set up their shmem allocations */ - if (shmem_startup_hook) - shmem_startup_hook(); + process_shmem_startup(); } #endif @@ -243,8 +243,7 @@ CreateSharedMemoryAndSemaphores(void) /* * Now give loadable modules a chance to set up their shmem allocations */ - if (shmem_startup_hook) - shmem_startup_hook(); + process_shmem_startup(); } /* @@ -386,3 +385,12 @@ InitializeShmemGUCs(void) sprintf(buf, "%d", num_semas); SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); } + +void +process_shmem_startup(void) +{ + process_shmem_startup_in_progress = true; + if (shmem_startup_hook) + shmem_startup_hook(); + process_shmem_startup_in_progress = false; +} diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 258cdebd0f5..5249e6bc509 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -80,6 +80,7 @@ #include "pg_trace.h" #include "pgstat.h" #include "port/pg_bitutils.h" +#include "storage/ipc.h" #include "storage/proc.h" #include "storage/proclist.h" #include "storage/procnumber.h" @@ -522,6 +523,11 @@ InitLWLockAccess(void) * Caller needs to retrieve the requested number of LWLocks starting from * the base lock address returned by this API. This can be used for * tranches that are requested by using RequestNamedLWLockTranche() API. + * + * Backends may not inherit NamedLWLockTrancheRequestArray, such as + * EXEC_BACKEND. It's not worth the effort to guarantee this, because + * extensions should only need to acquire a pointer to the LWLocks in the + * startup hook. */ LWLockPadded * GetNamedLWLockTranche(const char *tranche_name) @@ -529,6 +535,9 @@ GetNamedLWLockTranche(const char *tranche_name) int lock_pos; int i; + if (!process_shmem_startup_in_progress) + elog(ERROR, "cannot return the address of LWLocks outside of shmem_startup_hook"); + /* * Obtain the position of base address of LWLock belonging to requested * tranche_name in MainLWLockArray. LWLocks for named tranches are placed diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index 3baf418b3d1..3a3a1d311c3 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -76,9 +76,11 @@ extern void check_on_shmem_exit_lists_are_empty(void); /* ipci.c */ extern PGDLLIMPORT shmem_startup_hook_type shmem_startup_hook; +extern PGDLLIMPORT bool process_shmem_startup_in_progress; extern Size CalculateShmemSize(int *num_semaphores); extern void CreateSharedMemoryAndSemaphores(void); +extern void process_shmem_startup(void); #ifdef EXEC_BACKEND extern void AttachSharedMemoryStructs(void); #endif -- 2.43.0