aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/postmaster/postmaster.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index c01c497ff0d..69d661fdd00 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4417,6 +4417,7 @@ internal_forkexec(int argc, char *argv[], Port *port)
static pid_t
internal_forkexec(int argc, char *argv[], Port *port)
{
+ int retry_count = 0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
int i;
@@ -4434,6 +4435,9 @@ internal_forkexec(int argc, char *argv[], Port *port)
Assert(strncmp(argv[1], "--fork", 6) == 0);
Assert(argv[2] == NULL);
+ /* Resume here if we need to retry */
+retry:
+
/* Set up shared memory for parameter passing */
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
@@ -4525,22 +4529,26 @@ internal_forkexec(int argc, char *argv[], Port *port)
/*
* Reserve the memory region used by our main shared memory segment before
- * we resume the child process.
+ * we resume the child process. Normally this should succeed, but if ASLR
+ * is active then it might sometimes fail due to the stack or heap having
+ * gotten mapped into that range. In that case, just terminate the
+ * process and retry.
*/
if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
{
- /*
- * Failed to reserve the memory, so terminate the newly created
- * process and give up.
- */
+ /* pgwin32_ReserveSharedMemoryRegion already made a log entry */
if (!TerminateProcess(pi.hProcess, 255))
ereport(LOG,
(errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
GetLastError())));
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
- return -1; /* logging done made by
- * pgwin32_ReserveSharedMemoryRegion() */
+ if (++retry_count < 100)
+ goto retry;
+ ereport(LOG,
+ (errmsg("giving up after too many tries to reserve shared memory"),
+ errhint("This might be caused by ASLR or antivirus software.")));
+ return -1;
}
/*