From 2216cd8a1513120b7814a736b344f689dc75b37b Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 21 Oct 2023 17:40:26 +1300
Subject: [PATCH] Fix min_dynamic_shared_memory on Windows.

When min_dynamic_shared_memory is set above 0, we try to find space in a
region of the main shared memory area instead of calling out to
dsm_impl_XXX() routines.  The dsm_pin_segment() and dsm_unpin_segment()
routines had a bug: they called dsm_impl_XXX() routines even for main
region segments.  Nobody noticed before now because those routines do
nothing on Unix, but on Windows they'd fail while attempting to
duplicate an invalid Windows HANDLE.  Add the missing gating.

Back-patch to 14, where commit 84b1c63a added this feature.  Fixes
pgsql-bugs bug #18165.

Reported-by: Maxime Boyer <maxime.boyer@cra-arc.gc.ca>
Discussion: https://postgr.es/m/18165-bf4f525cea6e51de%40postgresql.org
---
 src/backend/storage/ipc/dsm.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 10b029bb16..cef547bb6c 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -938,7 +938,8 @@ dsm_pin_segment(dsm_segment *seg)
 	LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
 	if (dsm_control->item[seg->control_slot].pinned)
 		elog(ERROR, "cannot pin a segment that is already pinned");
-	dsm_impl_pin_segment(seg->handle, seg->impl_private, &handle);
+	if (!is_main_region_dsm_handle(seg->handle))
+		dsm_impl_pin_segment(seg->handle, seg->impl_private, &handle);
 	dsm_control->item[seg->control_slot].pinned = true;
 	dsm_control->item[seg->control_slot].refcnt++;
 	dsm_control->item[seg->control_slot].impl_private_pm_handle = handle;
@@ -995,8 +996,9 @@ dsm_unpin_segment(dsm_handle handle)
 	 * releasing the lock, because impl_private_pm_handle may get modified by
 	 * dsm_impl_unpin_segment.
 	 */
-	dsm_impl_unpin_segment(handle,
-						   &dsm_control->item[control_slot].impl_private_pm_handle);
+	if (!is_main_region_dsm_handle(handle))
+		dsm_impl_unpin_segment(handle,
+							   &dsm_control->item[control_slot].impl_private_pm_handle);
 
 	/* Note that 1 means no references (0 means unused slot). */
 	if (--dsm_control->item[control_slot].refcnt == 1)
-- 
2.42.0

