diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index 4ee453e..11c913a 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -42,6 +42,7 @@ #include "utils/guc.h" #include "utils/memutils.h" #include "utils/resowner_private.h" +#include "postmaster/postmaster.h" #define PG_DYNSHMEM_STATE_FILE PG_DYNSHMEM_DIR "/state" #define PG_DYNSHMEM_NEW_STATE_FILE PG_DYNSHMEM_DIR "/state.new" @@ -886,6 +887,52 @@ dsm_keep_mapping(dsm_segment *seg) } /* + * Keep a dynamic shared memory segment until end of postmaster. + * + * By default, segments are owned by the current resource owner, which + * typically means they stick around for the duration of the current query + * only. + */ +void +dsm_keep_segment(dsm_segment *seg) +{ + /* + * Bump reference count for this segment in shared memory. This will + * ensure that even if there is no session which is attached to this + * segment, it will stay till postmaster lifetime. For windows, we + * need to duplicate segment handle for postmaster process, as it + * automatically drops segment if all referring sessions end. + */ + LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE); + dsm_control->item[seg->control_slot].refcnt++; + LWLockRelease(DynamicSharedMemoryControlLock); + +#ifdef WIN32 + { + HANDLE hmap2; + + if (!DuplicateHandle(GetCurrentProcess(), + seg->impl_private, + PostmasterHandle, + &hmap2, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)) + { + char name[64]; + + snprintf(name, 64, "Global/PostgreSQL.%u", seg->handle); + _dosmaperr(GetLastError()); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not retain segment \"%s\" for postmaster lifetime: %m", + name))); + } + } +#endif +} + +/* * Find an existing mapping for a shared memory segment, if there is one. */ dsm_segment * diff --git a/src/include/storage/dsm.h b/src/include/storage/dsm.h index 71901bf..16afef3 100644 --- a/src/include/storage/dsm.h +++ b/src/include/storage/dsm.h @@ -30,6 +30,7 @@ extern void dsm_detach(dsm_segment *seg); /* Resource management functions. */ extern void dsm_keep_mapping(dsm_segment *seg); +extern void dsm_keep_segment(dsm_segment *seg); extern dsm_segment *dsm_find_mapping(dsm_handle h); /* Informational functions. */