diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c index 6df7413fe9b..cb944edd8df 100644 --- a/src/backend/storage/ipc/ipc.c +++ b/src/backend/storage/ipc/ipc.c @@ -29,6 +29,7 @@ #endif #include "storage/dsm.h" #include "storage/ipc.h" +#include "storage/lwlock.h" #include "tcop/tcopprot.h" @@ -229,13 +230,19 @@ shmem_exit(int code) { shmem_exit_inprogress = true; + /* + * Release any LWLocks we might be holding before callbacks run. This + * prevents accessing locks in detached DSM segments and allows callbacks + * to acquire new locks. + */ + LWLockReleaseAll(); + /* * Call before_shmem_exit callbacks. * * These should be things that need most of the system to still be up and * working, such as cleanup of temp relations, which requires catalog - * access; or things that need to be completed because later cleanup steps - * depend on them, such as releasing lwlocks. + * access. */ elog(DEBUG3, "shmem_exit(%d): %d before_shmem_exit callbacks to make", code, before_shmem_exit_index); diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index a133c97b992..517c55375b4 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -1883,6 +1883,10 @@ LWLockReleaseClearVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val) * unchanged by this operation. This is necessary since InterruptHoldoffCount * has been set to an appropriate level earlier in error recovery. We could * decrement it below zero if we allow it to drop for each released lock! + * + * Note that this function must be safe to call even before the LWLock + * subsystem has been initialized (e.g., during early startup failures). + * In that case, num_held_lwlocks will be 0 and we do nothing. */ void LWLockReleaseAll(void) @@ -1893,6 +1897,8 @@ LWLockReleaseAll(void) LWLockRelease(held_lwlocks[num_held_lwlocks - 1].lock); } + + Assert(num_held_lwlocks == 0); }