Amit Kapila <amit.kapil...@gmail.com> writes:
> Okay, I have added the comment to explain the same.  I have also
> modified the patch to adjust the looping as per your suggestion.

I took a quick look at this, and it seems rather beside the point.
You can't just loop inside an already-forked process and expect
that address space that was previously unavailable will suddenly
become available, when the problem is that the executable itself
(or some shared library) is mapped into the space you want.
What we have to do in order to retry is to fork an entire new
process, whose address space will hopefully get laid out differently.

While it's possible we could do that in a platform-independent
way, it would be pretty invasive and I don't see the value.
The implementation I'd had in mind originally was to put a loop
inside postmaster.c's internal_forkexec (win32 version), such
that if pgwin32_ReserveSharedMemoryRegion failed, it would
terminate/close up the subprocess as it already does, but then
go back around and do another CreateProcess.  Perhaps it's as
simple as the attached, but I'm not in a position to test it.

Assuming this passes minimal smoke testing, the way to actually test
it is to undo the hack in the MSVC build scripts that disables ASLR,
and then (on a Windows version where ASLR is active) run it until
you've seen a few occurrences of the retry, which should be detectable
by looking for bleats from pgwin32_ReserveSharedMemoryRegion
in the postmaster log.

                        regards, tom lane

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 35b4ec8..e30b0c6 100644
*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
*************** internal_forkexec(int argc, char *argv[]
*** 4487,4492 ****
--- 4487,4493 ----
  static pid_t
  internal_forkexec(int argc, char *argv[], Port *port)
  {
+ 	int			retry_count = 0;
  	STARTUPINFO si;
  	PROCESS_INFORMATION pi;
  	int			i;
*************** internal_forkexec(int argc, char *argv[]
*** 4504,4509 ****
--- 4505,4513 ----
  	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);
*************** internal_forkexec(int argc, char *argv[]
*** 4595,4616 ****
  
  	/*
  	 * Reserve the memory region used by our main shared memory segment before
! 	 * we resume the child process.
  	 */
  	if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
  	{
! 		/*
! 		 * Failed to reserve the memory, so terminate the newly created
! 		 * process and give up.
! 		 */
  		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() */
  	}
  
  	/*
--- 4599,4624 ----
  
  	/*
  	 * Reserve the memory region used by our main shared memory segment before
! 	 * we resume the child process.  Normally this should succeed, but if ASLR
! 	 * is active then it might sometimes fail due to the executable having
! 	 * gotten mapped into that range.  In that case, just terminate the
! 	 * process and retry.
  	 */
  	if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
  	{
! 		/* 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);
! 		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;
  	}
  
  	/*
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to