mirror of
https://github.com/postgres/postgres.git
synced 2025-10-15 05:46:52 +03:00
Move named LWLock tranche requests to shared memory.
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
This commit is contained in:
@@ -101,6 +101,7 @@ typedef struct
|
|||||||
struct InjectionPointsCtl *ActiveInjectionPoints;
|
struct InjectionPointsCtl *ActiveInjectionPoints;
|
||||||
#endif
|
#endif
|
||||||
int NamedLWLockTrancheRequests;
|
int NamedLWLockTrancheRequests;
|
||||||
|
NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray;
|
||||||
char **LWLockTrancheNames;
|
char **LWLockTrancheNames;
|
||||||
int *LWLockCounter;
|
int *LWLockCounter;
|
||||||
LWLockPadded *MainLWLockArray;
|
LWLockPadded *MainLWLockArray;
|
||||||
@@ -761,6 +762,7 @@ save_backend_variables(BackendParameters *param,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests;
|
param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests;
|
||||||
|
param->NamedLWLockTrancheRequestArray = NamedLWLockTrancheRequestArray;
|
||||||
param->LWLockTrancheNames = LWLockTrancheNames;
|
param->LWLockTrancheNames = LWLockTrancheNames;
|
||||||
param->LWLockCounter = LWLockCounter;
|
param->LWLockCounter = LWLockCounter;
|
||||||
param->MainLWLockArray = MainLWLockArray;
|
param->MainLWLockArray = MainLWLockArray;
|
||||||
@@ -1022,6 +1024,7 @@ restore_backend_variables(BackendParameters *param)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
|
NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
|
||||||
|
NamedLWLockTrancheRequestArray = param->NamedLWLockTrancheRequestArray;
|
||||||
LWLockTrancheNames = param->LWLockTrancheNames;
|
LWLockTrancheNames = param->LWLockTrancheNames;
|
||||||
LWLockCounter = param->LWLockCounter;
|
LWLockCounter = param->LWLockCounter;
|
||||||
MainLWLockArray = param->MainLWLockArray;
|
MainLWLockArray = param->MainLWLockArray;
|
||||||
|
@@ -184,14 +184,13 @@ typedef struct NamedLWLockTrancheRequest
|
|||||||
int num_lwlocks;
|
int num_lwlocks;
|
||||||
} NamedLWLockTrancheRequest;
|
} NamedLWLockTrancheRequest;
|
||||||
|
|
||||||
static NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NamedLWLockTrancheRequests is the valid length of the request array. This
|
* NamedLWLockTrancheRequests is the valid length of the request array. These
|
||||||
* variable is non-static so that postmaster.c can copy them to child processes
|
* variables are non-static so that launch_backend.c can copy them to child
|
||||||
* in EXEC_BACKEND builds.
|
* processes in EXEC_BACKEND builds.
|
||||||
*/
|
*/
|
||||||
int NamedLWLockTrancheRequests = 0;
|
int NamedLWLockTrancheRequests = 0;
|
||||||
|
NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray = NULL;
|
||||||
|
|
||||||
/* shared memory counter of registered tranches */
|
/* shared memory counter of registered tranches */
|
||||||
int *LWLockCounter = NULL;
|
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, sizeof(char *)));
|
||||||
size = add_size(size, mul_size(MAX_NAMED_TRANCHES, NAMEDATALEN));
|
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. */
|
/* Space for the LWLock array, plus room for cache line alignment. */
|
||||||
size = add_size(size, LWLOCK_PADDED_SIZE);
|
size = add_size(size, LWLOCK_PADDED_SIZE);
|
||||||
size = add_size(size, mul_size(numLocks, sizeof(LWLockPadded)));
|
size = add_size(size, mul_size(numLocks, sizeof(LWLockPadded)));
|
||||||
@@ -443,6 +450,20 @@ CreateLWLocks(void)
|
|||||||
ptr += NAMEDATALEN;
|
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 */
|
/* Ensure desired alignment of LWLock array */
|
||||||
ptr += LWLOCK_PADDED_SIZE - ((uintptr_t) ptr) % LWLOCK_PADDED_SIZE;
|
ptr += LWLOCK_PADDED_SIZE - ((uintptr_t) ptr) % LWLOCK_PADDED_SIZE;
|
||||||
MainLWLockArray = (LWLockPadded *) ptr;
|
MainLWLockArray = (LWLockPadded *) ptr;
|
||||||
|
@@ -73,8 +73,12 @@ typedef union LWLockPadded
|
|||||||
|
|
||||||
extern PGDLLIMPORT LWLockPadded *MainLWLockArray;
|
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 char **LWLockTrancheNames;
|
||||||
extern PGDLLIMPORT int NamedLWLockTrancheRequests;
|
extern PGDLLIMPORT int NamedLWLockTrancheRequests;
|
||||||
|
extern PGDLLIMPORT NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray;
|
||||||
extern PGDLLIMPORT int *LWLockCounter;
|
extern PGDLLIMPORT int *LWLockCounter;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user