diff options
Diffstat (limited to 'src/backend/storage/ipc/dsm_impl.c')
-rw-r--r-- | src/backend/storage/ipc/dsm_impl.c | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c index 173b9822191..c07a5c6b151 100644 --- a/src/backend/storage/ipc/dsm_impl.c +++ b/src/backend/storage/ipc/dsm_impl.c @@ -987,8 +987,8 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, #endif /* - * Implementation-specific actions that must be performed when a segment - * is to be preserved until postmaster shutdown. + * Implementation-specific actions that must be performed when a segment is to + * be preserved even when no backend has it attached. * * Except on Windows, we don't need to do anything at all. But since Windows * cleans up segments automatically when no references remain, we duplicate @@ -996,7 +996,8 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, * do anything to receive the handle; Windows transfers it automatically. */ void -dsm_impl_pin_segment(dsm_handle handle, void *impl_private) +dsm_impl_pin_segment(dsm_handle handle, void *impl_private, + void **impl_private_pm_handle) { switch (dynamic_shared_memory_type) { @@ -1018,6 +1019,56 @@ dsm_impl_pin_segment(dsm_handle handle, void *impl_private) errmsg("could not duplicate handle for \"%s\": %m", name))); } + + /* + * Here, we remember the handle that we created in the + * postmaster process. This handle isn't actually usable in + * any process other than the postmaster, but that doesn't + * matter. We're just holding onto it so that, if the segment + * is unpinned, dsm_impl_unpin_segment can close it. + */ + *impl_private_pm_handle = hmap; + break; + } +#endif + default: + break; + } +} + +/* + * Implementation-specific actions that must be performed when a segment is no + * longer to be preserved, so that it will be cleaned up when all backends + * have detached from it. + * + * Except on Windows, we don't need to do anything at all. For Windows, we + * close the extra handle that dsm_impl_pin_segment created in the + * postmaster's process space. + */ +void +dsm_impl_unpin_segment(dsm_handle handle, void **impl_private) +{ + switch (dynamic_shared_memory_type) + { +#ifdef USE_DSM_WINDOWS + case DSM_IMPL_WINDOWS: + { + if (*impl_private && + !DuplicateHandle(PostmasterHandle, *impl_private, + NULL, NULL, 0, FALSE, + DUPLICATE_CLOSE_SOURCE)) + { + char name[64]; + + snprintf(name, 64, "%s.%u", SEGMENT_NAME_PREFIX, handle); + _dosmaperr(GetLastError()); + ereport(ERROR, + (errcode_for_dynamic_shared_memory(), + errmsg("could not duplicate handle for \"%s\": %m", + name))); + } + + *impl_private = NULL; break; } #endif |