aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/port/sysv_shmem.c53
-rw-r--r--src/backend/port/win32_shmem.c82
-rw-r--r--src/backend/postmaster/postmaster.c5
-rw-r--r--src/include/storage/pg_shmem.h1
4 files changed, 116 insertions, 25 deletions
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 8be5bbe1aba..437ae4625dc 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -195,7 +195,7 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
/****************************************************************************/
/* IpcMemoryDetach(status, shmaddr) removes a shared memory segment */
-/* from process' address spaceq */
+/* from process' address space */
/* (called as an on_shmem_exit callback, hence funny argument list) */
/****************************************************************************/
static void
@@ -583,9 +583,10 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
/*
* PGSharedMemoryReAttach
*
- * Re-attach to an already existing shared memory segment. In the non
- * EXEC_BACKEND case this is not used, because postmaster children inherit
- * the shared memory segment attachment via fork().
+ * This is called during startup of a postmaster child process to re-attach to
+ * an already existing shared memory segment. This is needed only in the
+ * EXEC_BACKEND case; otherwise postmaster children inherit the shared memory
+ * segment attachment via fork().
*
* UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
* routine. The caller must have already restored them to the postmaster's
@@ -619,16 +620,52 @@ PGSharedMemoryReAttach(void)
UsedShmemSegAddr = hdr; /* probably redundant */
}
+
+/*
+ * PGSharedMemoryNoReAttach
+ *
+ * This is called during startup of a postmaster child process when we choose
+ * *not* to re-attach to the existing shared memory segment. We must clean up
+ * to leave things in the appropriate state. This is not used in the non
+ * EXEC_BACKEND case, either.
+ *
+ * The child process startup logic might or might not call PGSharedMemoryDetach
+ * after this; make sure that it will be a no-op if called.
+ *
+ * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
+ * routine. The caller must have already restored them to the postmaster's
+ * values.
+ */
+void
+PGSharedMemoryNoReAttach(void)
+{
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(IsUnderPostmaster);
+
+#ifdef __CYGWIN__
+ /* cygipc (currently) appears to not detach on exec. */
+ PGSharedMemoryDetach();
+#endif
+
+ /* For cleanliness, reset UsedShmemSegAddr to show we're not attached. */
+ UsedShmemSegAddr = NULL;
+ /* And the same for UsedShmemSegID. */
+ UsedShmemSegID = 0;
+}
+
#endif /* EXEC_BACKEND */
/*
* PGSharedMemoryDetach
*
* Detach from the shared memory segment, if still attached. This is not
- * intended for use by the process that originally created the segment
- * (it will have an on_shmem_exit callback registered to do that). Rather,
- * this is for subprocesses that have inherited an attachment and want to
- * get rid of it.
+ * intended to be called explicitly by the process that originally created the
+ * segment (it will have an on_shmem_exit callback registered to do that).
+ * Rather, this is for subprocesses that have inherited an attachment and want
+ * to get rid of it.
+ *
+ * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
+ * routine.
*/
void
PGSharedMemoryDetach(void)
diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
index db676278a69..110bdcc703d 100644
--- a/src/backend/port/win32_shmem.c
+++ b/src/backend/port/win32_shmem.c
@@ -17,7 +17,7 @@
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
-HANDLE UsedShmemSegID = 0;
+HANDLE UsedShmemSegID = INVALID_HANDLE_VALUE;
void *UsedShmemSegAddr = NULL;
static Size UsedShmemSegSize = 0;
@@ -83,7 +83,6 @@ GetSharedMemName(void)
* we only care about shmem segments that are associated with the intended
* DataDir. This is an important consideration since accidental matches of
* shmem segment IDs are reasonably common.
- *
*/
bool
PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
@@ -115,7 +114,6 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
* or recycle any existing segment. On win32, we always create a new segment,
* since there is no need for recycling (segments go away automatically
* when the last backend exits)
- *
*/
PGShmemHeader *
PGSharedMemoryCreate(Size size, bool makePrivate, int port,
@@ -218,9 +216,6 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError());
- /* Register on-exit routine to delete the new segment */
- on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2));
-
/*
* Get a pointer to the new shared memory segment. Map the whole segment
* at once, and let the system decide on the initial address.
@@ -254,6 +249,9 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
UsedShmemSegSize = size;
UsedShmemSegID = hmap2;
+ /* Register on-exit routine to delete the new segment */
+ on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2));
+
*shim = hdr;
return hdr;
}
@@ -261,8 +259,9 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
/*
* PGSharedMemoryReAttach
*
- * Re-attach to an already existing shared memory segment. Use the
- * handle inherited from the postmaster.
+ * This is called during startup of a postmaster child process to re-attach to
+ * an already existing shared memory segment, using the handle inherited from
+ * the postmaster.
*
* UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
* routine. The caller must have already restored them to the postmaster's
@@ -299,36 +298,87 @@ PGSharedMemoryReAttach(void)
}
/*
+ * PGSharedMemoryNoReAttach
+ *
+ * This is called during startup of a postmaster child process when we choose
+ * *not* to re-attach to the existing shared memory segment. We must clean up
+ * to leave things in the appropriate state.
+ *
+ * The child process startup logic might or might not call PGSharedMemoryDetach
+ * after this; make sure that it will be a no-op if called.
+ *
+ * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
+ * routine. The caller must have already restored them to the postmaster's
+ * values.
+ */
+void
+PGSharedMemoryNoReAttach(void)
+{
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(IsUnderPostmaster);
+
+ /*
+ * Under Windows we will not have mapped the segment, so we don't need to
+ * un-map it. Just reset UsedShmemSegAddr to show we're not attached.
+ */
+ UsedShmemSegAddr = NULL;
+
+ /*
+ * We *must* close the inherited shmem segment handle, else Windows will
+ * consider the existence of this process to mean it can't release the
+ * shmem segment yet. We can now use PGSharedMemoryDetach to do that.
+ */
+ PGSharedMemoryDetach();
+}
+
+/*
* PGSharedMemoryDetach
*
* Detach from the shared memory segment, if still attached. This is not
- * intended for use by the process that originally created the segment. Rather,
- * this is for subprocesses that have inherited an attachment and want to
- * get rid of it.
+ * intended to be called explicitly by the process that originally created the
+ * segment (it will have an on_shmem_exit callback registered to do that).
+ * Rather, this is for subprocesses that have inherited an attachment and want
+ * to get rid of it.
+ *
+ * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
+ * routine.
*/
void
PGSharedMemoryDetach(void)
{
+ /* Unmap the view, if it's mapped */
if (UsedShmemSegAddr != NULL)
{
if (!UnmapViewOfFile(UsedShmemSegAddr))
- elog(LOG, "could not unmap view of shared memory: error code %lu", GetLastError());
+ elog(LOG, "could not unmap view of shared memory: error code %lu",
+ GetLastError());
UsedShmemSegAddr = NULL;
}
+
+ /* And close the shmem handle, if we have one */
+ if (UsedShmemSegID != INVALID_HANDLE_VALUE)
+ {
+ if (!CloseHandle(UsedShmemSegID))
+ elog(LOG, "could not close handle to shared memory: error code %lu",
+ GetLastError());
+
+ UsedShmemSegID = INVALID_HANDLE_VALUE;
+ }
}
/*
- * pgwin32_SharedMemoryDelete(status, shmId) deletes a shared memory segment
- * (called as an on_shmem_exit callback, hence funny argument list)
+ * pgwin32_SharedMemoryDelete
+ *
+ * Detach from and delete the shared memory segment
+ * (called as an on_shmem_exit callback, hence funny argument list)
*/
static void
pgwin32_SharedMemoryDelete(int status, Datum shmId)
{
+ Assert(DatumGetPointer(shmId) == UsedShmemSegID);
PGSharedMemoryDetach();
- if (!CloseHandle(DatumGetPointer(shmId)))
- elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError());
}
/*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 24e84043e29..90c2f4a5e32 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4628,7 +4628,8 @@ SubPostmasterMain(int argc, char *argv[])
/*
* If appropriate, physically re-attach to shared memory segment. We want
* to do this before going any further to ensure that we can attach at the
- * same address the postmaster used.
+ * same address the postmaster used. On the other hand, if we choose not
+ * to re-attach, we may have other cleanup to do.
*/
if (strcmp(argv[1], "--forkbackend") == 0 ||
strcmp(argv[1], "--forkavlauncher") == 0 ||
@@ -4636,6 +4637,8 @@ SubPostmasterMain(int argc, char *argv[])
strcmp(argv[1], "--forkboot") == 0 ||
strncmp(argv[1], "--forkbgworker=", 15) == 0)
PGSharedMemoryReAttach();
+ else
+ PGSharedMemoryNoReAttach();
/* autovacuum needs this set before calling InitProcess */
if (strcmp(argv[1], "--forkavlauncher") == 0)
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index 0b169aff69d..9dbcbce0692 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -61,6 +61,7 @@ extern void *UsedShmemSegAddr;
#ifdef EXEC_BACKEND
extern void PGSharedMemoryReAttach(void);
+extern void PGSharedMemoryNoReAttach(void);
#endif
extern PGShmemHeader *PGSharedMemoryCreate(Size size, bool makePrivate,