Fix min_dynamic_shared_memory on Windows.
authorThomas Munro <[email protected]>
Sat, 21 Oct 2023 21:04:55 +0000 (10:04 +1300)
committerThomas Munro <[email protected]>
Sat, 21 Oct 2023 21:05:59 +0000 (10:05 +1300)
When min_dynamic_shared_memory is set above 0, we try to find space in a
pre-allocated region of the main shared memory area instead of calling
dsm_impl_XXX() routines to allocate more.  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 <[email protected]>
Tested-by: Alexander Lakhin <[email protected]>
Discussion: https://postgr.es/m/18165-bf4f525cea6e51de%40postgresql.org

src/backend/storage/ipc/dsm.c

index b461a5f7e96e069828a5164ab5d95078f1426595..83ca9595e8e33d0446e0a53678bfe0b110728c68 100644 (file)
@@ -920,7 +920,7 @@ dsm_unpin_mapping(dsm_segment *seg)
 void
 dsm_pin_segment(dsm_segment *seg)
 {
-   void       *handle;
+   void       *handle = NULL;
 
    /*
     * Bump reference count for this segment in shared memory. This will
@@ -931,7 +931,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;
@@ -988,8 +989,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)