Skip to content

Commit a4a590e

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 b33faac commit a4a590e

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

src/backend/postmaster/postmaster.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3937,6 +3937,7 @@ internal_forkexec(int argc, char *argv[], Port *port)
39373937
static pid_t
39383938
internal_forkexec(int argc, char *argv[], Port *port)
39393939
{
3940+
int retry_count = 0;
39403941
STARTUPINFO si;
39413942
PROCESS_INFORMATION pi;
39423943
int i;
@@ -3954,6 +3955,9 @@ internal_forkexec(int argc, char *argv[], Port *port)
39543955
Assert(strncmp(argv[1], "--fork", 6) == 0);
39553956
Assert(argv[2] == NULL);
39563957

3958+
/* Resume here if we need to retry */
3959+
retry:
3960+
39573961
/* Set up shared memory for parameter passing */
39583962
ZeroMemory(&sa, sizeof(sa));
39593963
sa.nLength = sizeof(sa);
@@ -4045,22 +4049,26 @@ internal_forkexec(int argc, char *argv[], Port *port)
40454049

40464050
/*
40474051
* Reserve the memory region used by our main shared memory segment before
4048-
* we resume the child process.
4052+
* we resume the child process. Normally this should succeed, but if ASLR
4053+
* is active then it might sometimes fail due to the stack or heap having
4054+
* gotten mapped into that range. In that case, just terminate the
4055+
* process and retry.
40494056
*/
40504057
if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
40514058
{
4052-
/*
4053-
* Failed to reserve the memory, so terminate the newly created
4054-
* process and give up.
4055-
*/
4059+
/* pgwin32_ReserveSharedMemoryRegion already made a log entry */
40564060
if (!TerminateProcess(pi.hProcess, 255))
40574061
ereport(LOG,
40584062
(errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
40594063
GetLastError())));
40604064
CloseHandle(pi.hProcess);
40614065
CloseHandle(pi.hThread);
4062-
return -1; /* logging done made by
4063-
* pgwin32_ReserveSharedMemoryRegion() */
4066+
if (++retry_count < 100)
4067+
goto retry;
4068+
ereport(LOG,
4069+
(errmsg("giving up after too many tries to reserve shared memory"),
4070+
errhint("This might be caused by ASLR or antivirus software.")));
4071+
return -1;
40644072
}
40654073

40664074
/*

0 commit comments

Comments
 (0)