Skip to content

Commit 8722017

Browse files
committed
Allow dynamic shared memory segments to be kept until shutdown.
Amit Kapila, reviewed by Kyotaro Horiguchi, with some further changes by me.
1 parent 5a991ef commit 8722017

File tree

4 files changed

+75
-1
lines changed

4 files changed

+75
-1
lines changed

src/backend/storage/ipc/dsm.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,33 @@ dsm_keep_mapping(dsm_segment *seg)
885885
}
886886
}
887887

888+
/*
889+
* Keep a dynamic shared memory segment until postmaster shutdown.
890+
*
891+
* This function should not be called more than once per segment;
892+
* on Windows, doing so will create unnecessary handles which will
893+
* consume system resources to no benefit.
894+
*
895+
* Note that this function does not arrange for the current process to
896+
* keep the segment mapped indefinitely; if that behavior is desired,
897+
* dsm_keep_mapping() should be used from each process that needs to
898+
* retain the mapping.
899+
*/
900+
void
901+
dsm_keep_segment(dsm_segment *seg)
902+
{
903+
/*
904+
* Bump reference count for this segment in shared memory. This will
905+
* ensure that even if there is no session which is attached to this
906+
* segment, it will remain until postmaster shutdown.
907+
*/
908+
LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
909+
dsm_control->item[seg->control_slot].refcnt++;
910+
LWLockRelease(DynamicSharedMemoryControlLock);
911+
912+
dsm_impl_keep_segment(seg->handle, seg->impl_private);
913+
}
914+
888915
/*
889916
* Find an existing mapping for a shared memory segment, if there is one.
890917
*/

src/backend/storage/ipc/dsm_impl.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "storage/fd.h"
6868
#include "utils/guc.h"
6969
#include "utils/memutils.h"
70+
#include "postmaster/postmaster.h"
7071

7172
#ifdef USE_DSM_POSIX
7273
static bool dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
@@ -113,6 +114,8 @@ int dynamic_shared_memory_type;
113114
/* Size of buffer to be used for zero-filling. */
114115
#define ZBUFFER_SIZE 8192
115116

117+
#define SEGMENT_NAME_PREFIX "Global/PostgreSQL"
118+
116119
/*------
117120
* Perform a low-level shared memory operation in a platform-specific way,
118121
* as dictated by the selected implementation. Each implementation is
@@ -635,7 +638,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
635638
* convention similar to main shared memory. We can change here once
636639
* issue mentioned in GetSharedMemName is resolved.
637640
*/
638-
snprintf(name, 64, "Global/PostgreSQL.%u", handle);
641+
snprintf(name, 64, "%s.%u", SEGMENT_NAME_PREFIX, handle);
639642

640643
/*
641644
* Handle teardown cases. Since Windows automatically destroys the object
@@ -982,6 +985,46 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
982985
}
983986
#endif
984987

988+
/*
989+
* Implementation-specific actions that must be performed when a segment
990+
* is to be preserved until postmaster shutdown.
991+
*
992+
* Except on Windows, we don't need to do anything at all. But since Windows
993+
* cleans up segments automatically when no references remain, we duplicate
994+
* the segment handle into the postmaster process. The postmaster needn't
995+
* do anything to receive the handle; Windows transfers it automatically.
996+
*/
997+
void
998+
dsm_impl_keep_segment(dsm_handle handle, void *impl_private)
999+
{
1000+
switch (dynamic_shared_memory_type)
1001+
{
1002+
#ifdef USE_DSM_WINDOWS
1003+
case DSM_IMPL_WINDOWS:
1004+
{
1005+
HANDLE hmap;
1006+
1007+
if (!DuplicateHandle(GetCurrentProcess(), impl_private,
1008+
PostmasterHandle, &hmap, 0, FALSE,
1009+
DUPLICATE_SAME_ACCESS))
1010+
{
1011+
char name[64];
1012+
1013+
snprintf(name, 64, "%s.%u", SEGMENT_NAME_PREFIX, handle);
1014+
_dosmaperr(GetLastError());
1015+
ereport(ERROR,
1016+
(errcode_for_dynamic_shared_memory(),
1017+
errmsg("could not duplicate handle for \"%s\": %m",
1018+
name)));
1019+
}
1020+
break;
1021+
}
1022+
#endif
1023+
default:
1024+
break;
1025+
}
1026+
}
1027+
9851028
static int
9861029
errcode_for_dynamic_shared_memory()
9871030
{

src/include/storage/dsm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ extern void dsm_detach(dsm_segment *seg);
3030

3131
/* Resource management functions. */
3232
extern void dsm_keep_mapping(dsm_segment *seg);
33+
extern void dsm_keep_segment(dsm_segment *seg);
3334
extern dsm_segment *dsm_find_mapping(dsm_handle h);
3435

3536
/* Informational functions. */

src/include/storage/dsm_impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,7 @@ extern bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size,
7272
/* Some implementations cannot resize segments. Can this one? */
7373
extern bool dsm_impl_can_resize(void);
7474

75+
/* Implementation-dependent actions required to keep segment until shudown. */
76+
extern void dsm_impl_keep_segment(dsm_handle handle, void *impl_private);
77+
7578
#endif /* DSM_IMPL_H */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy