mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
On Windows, ensure shared memory handle gets closed if not being used.
Postmaster child processes that aren't supposed to be attached to shared memory were not bothering to close the shared memory mapping handle they inherit from the postmaster process. That's mostly harmless, since the handle vanishes anyway when the child process exits -- but the syslogger process, if used, doesn't get killed and restarted during recovery from a backend crash. That meant that Windows doesn't see the shared memory mapping as becoming free, so it doesn't delete it and the postmaster is unable to create a new one, resulting in failure to recover from crashes whenever logging_collector is turned on. Per report from Dmitry Vasilyev. It's a bit astonishing that we'd not figured this out long ago, since it's been broken from the very beginnings of out native Windows support; probably some previously-unexplained trouble reports trace to this. A secondary problem is that on Cygwin (perhaps only in older versions?), exec() may not detach from the shared memory segment after all, in which case these child processes did remain attached to shared memory, posing the risk of an unexpected shared memory clobber if they went off the rails somehow. That may be a long-gone bug, but we can deal with it now if it's still live, by detaching within the infrastructure introduced here to deal with closing the handle. Back-patch to all supported branches. Tom Lane and Amit Kapila
This commit is contained in:
@ -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)
|
||||
|
Reference in New Issue
Block a user