Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c0077f7

Browse files
committed
On Windows, retry process creation if we fail to reserve shared memory.
We've heard occasional reports of backend launch failing because pgwin32_ReserveSharedMemoryRegion() fails, indicating that something has already used that address space in the child process. It's not very clear what, given that we disable ASLR in Windows builds, but suspicion falls on antivirus products. It'd be better if we didn't have to disable ASLR, anyway. So let's try to ameliorate the problem by retrying the process launch after such a failure, up to 100 times. Patch by me, based on previous work by Amit Kapila and others. This is a longstanding issue, so back-patch to all supported branches. Discussion: https://postgr.es/m/CAA4eK1+R6hSx6t_yvwtx+NRzneVp+MRqXAdGJZChcau8Uij-8g@mail.gmail.com
1 parent ef68c9f commit c0077f7

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

src/backend/postmaster/postmaster.c

+15-7
Original file line numberDiff line numberDiff line change
@@ -4447,6 +4447,7 @@ internal_forkexec(int argc, char *argv[], Port *port)
44474447
static pid_t
44484448
internal_forkexec(int argc, char *argv[], Port *port)
44494449
{
4450+
int retry_count = 0;
44504451
STARTUPINFO si;
44514452
PROCESS_INFORMATION pi;
44524453
int i;
@@ -4464,6 +4465,9 @@ internal_forkexec(int argc, char *argv[], Port *port)
44644465
Assert(strncmp(argv[1], "--fork", 6) == 0);
44654466
Assert(argv[2] == NULL);
44664467

4468+
/* Resume here if we need to retry */
4469+
retry:
4470+
44674471
/* Set up shared memory for parameter passing */
44684472
ZeroMemory(&sa, sizeof(sa));
44694473
sa.nLength = sizeof(sa);
@@ -4555,22 +4559,26 @@ internal_forkexec(int argc, char *argv[], Port *port)
45554559

45564560
/*
45574561
* Reserve the memory region used by our main shared memory segment before
4558-
* we resume the child process.
4562+
* we resume the child process. Normally this should succeed, but if ASLR
4563+
* is active then it might sometimes fail due to the stack or heap having
4564+
* gotten mapped into that range. In that case, just terminate the
4565+
* process and retry.
45594566
*/
45604567
if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
45614568
{
4562-
/*
4563-
* Failed to reserve the memory, so terminate the newly created
4564-
* process and give up.
4565-
*/
4569+
/* pgwin32_ReserveSharedMemoryRegion already made a log entry */
45664570
if (!TerminateProcess(pi.hProcess, 255))
45674571
ereport(LOG,
45684572
(errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
45694573
GetLastError())));
45704574
CloseHandle(pi.hProcess);
45714575
CloseHandle(pi.hThread);
4572-
return -1; /* logging done made by
4573-
* pgwin32_ReserveSharedMemoryRegion() */
4576+
if (++retry_count < 100)
4577+
goto retry;
4578+
ereport(LOG,
4579+
(errmsg("giving up after too many tries to reserve shared memory"),
4580+
errhint("This might be caused by ASLR or antivirus software.")));
4581+
return -1;
45744582
}
45754583

45764584
/*

0 commit comments

Comments
 (0)