mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
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
This commit is contained in:
parent
ef68c9f6eb
commit
c0077f7383
@ -4447,6 +4447,7 @@ internal_forkexec(int argc, char *argv[], Port *port)
|
|||||||
static pid_t
|
static pid_t
|
||||||
internal_forkexec(int argc, char *argv[], Port *port)
|
internal_forkexec(int argc, char *argv[], Port *port)
|
||||||
{
|
{
|
||||||
|
int retry_count = 0;
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
int i;
|
int i;
|
||||||
@ -4464,6 +4465,9 @@ internal_forkexec(int argc, char *argv[], Port *port)
|
|||||||
Assert(strncmp(argv[1], "--fork", 6) == 0);
|
Assert(strncmp(argv[1], "--fork", 6) == 0);
|
||||||
Assert(argv[2] == NULL);
|
Assert(argv[2] == NULL);
|
||||||
|
|
||||||
|
/* Resume here if we need to retry */
|
||||||
|
retry:
|
||||||
|
|
||||||
/* Set up shared memory for parameter passing */
|
/* Set up shared memory for parameter passing */
|
||||||
ZeroMemory(&sa, sizeof(sa));
|
ZeroMemory(&sa, sizeof(sa));
|
||||||
sa.nLength = sizeof(sa);
|
sa.nLength = sizeof(sa);
|
||||||
@ -4555,22 +4559,26 @@ internal_forkexec(int argc, char *argv[], Port *port)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Reserve the memory region used by our main shared memory segment before
|
* 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))
|
if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
|
||||||
{
|
{
|
||||||
/*
|
/* pgwin32_ReserveSharedMemoryRegion already made a log entry */
|
||||||
* Failed to reserve the memory, so terminate the newly created
|
|
||||||
* process and give up.
|
|
||||||
*/
|
|
||||||
if (!TerminateProcess(pi.hProcess, 255))
|
if (!TerminateProcess(pi.hProcess, 255))
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
|
(errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
|
||||||
GetLastError())));
|
GetLastError())));
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
return -1; /* logging done made by
|
if (++retry_count < 100)
|
||||||
* pgwin32_ReserveSharedMemoryRegion() */
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user