diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 124b214..c823dfd 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -709,9 +709,12 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
  * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
  * routine.  The caller must have already restored them to the postmaster's
  * values.
+ *
+ * Returns true if successfuly attached to pre-existing shared memory segment,
+ * false otherwise.
  */
-void
-PGSharedMemoryReAttach(void)
+bool
+PGSharedMemoryReAttach(int retry_count)
 {
 	IpcMemoryId shmid;
 	void	   *hdr;
@@ -722,21 +725,33 @@ PGSharedMemoryReAttach(void)
 
 #ifdef __CYGWIN__
 	/* cygipc (currently) appears to not detach on exec. */
-	PGSharedMemoryDetach();
-	UsedShmemSegAddr = origUsedShmemSegAddr;
+	if (!retry_count)
+	{
+		PGSharedMemoryDetach();
+		UsedShmemSegAddr = origUsedShmemSegAddr;
+	}
 #endif
 
 	elog(DEBUG3, "attaching to %p", UsedShmemSegAddr);
 	hdr = (void *) PGSharedMemoryAttach((IpcMemoryKey) UsedShmemSegID, &shmid);
 	if (hdr == NULL)
-		elog(FATAL, "could not reattach to shared memory (key=%d, addr=%p): %m",
+	{
+		elog(LOG, "could not reattach to shared memory (key=%d, addr=%p): %m",
 			 (int) UsedShmemSegID, UsedShmemSegAddr);
+		return false;
+	}
 	if (hdr != origUsedShmemSegAddr)
-		elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
+	{
+		elog(LOG, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
 			 hdr, origUsedShmemSegAddr);
+		shmdt((void *) hdr);
+		return false;
+	}
 	dsm_set_control_handle(((PGShmemHeader *) hdr)->dsm_control);
 
 	UsedShmemSegAddr = hdr;		/* probably redundant */
+
+	return true;
 }
 
 /*
diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
index 31489fc..5c344ee 100644
--- a/src/backend/port/win32_shmem.c
+++ b/src/backend/port/win32_shmem.c
@@ -266,9 +266,12 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
  * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
  * routine.  The caller must have already restored them to the postmaster's
  * values.
+ *
+ * Returns true if successfuly attached to pre-existing shared memory segment,
+ * false otherwise.
  */
-void
-PGSharedMemoryReAttach(void)
+bool
+PGSharedMemoryReAttach(int retry_count)
 {
 	PGShmemHeader *hdr;
 	void	   *origUsedShmemSegAddr = UsedShmemSegAddr;
@@ -277,24 +280,42 @@ PGSharedMemoryReAttach(void)
 	Assert(IsUnderPostmaster);
 
 	/*
-	 * Release memory region reservation that was made by the postmaster
+	 * On the first try, release memory region reservation that was made by
+	 * the postmaster.
 	 */
-	if (VirtualFree(UsedShmemSegAddr, 0, MEM_RELEASE) == 0)
-		elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
+	if (!retry_count && VirtualFree(UsedShmemSegAddr, 0, MEM_RELEASE) == 0)
+	{
+		elog(LOG, "failed to release reserved memory region (addr=%p): error code %lu",
 			 UsedShmemSegAddr, GetLastError());
+		return false;
+	}
 
 	hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
 	if (!hdr)
-		elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
+	{
+		elog(LOG, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
 			 UsedShmemSegID, UsedShmemSegAddr, GetLastError());
+		return false;
+	}
 	if (hdr != origUsedShmemSegAddr)
-		elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
+	{
+		elog(LOG, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
 			 hdr, origUsedShmemSegAddr);
+		UnmapViewOfFile(hdr);
+		return false;
+	}
 	if (hdr->magic != PGShmemMagic)
-		elog(FATAL, "reattaching to shared memory returned non-PostgreSQL memory");
+	{
+		elog(LOG, "reattaching to shared memory returned non-PostgreSQL memory");
+		UnmapViewOfFile(hdr);
+		return false;
+	}
+
 	dsm_set_control_handle(hdr->dsm_control);
 
 	UsedShmemSegAddr = hdr;		/* probably redundant */
+
+	return true;
 }
 
 /*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 35b4ec8..53b2b82 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4497,6 +4497,7 @@ internal_forkexec(int argc, char *argv[], Port *port)
 	SECURITY_ATTRIBUTES sa;
 	char		paramHandleStr[32];
 	win32_deadchild_waitinfo *childinfo;
+	bool		shm_reserved = false;
 
 	/* Make sure caller set up argv properly */
 	Assert(argc >= 3);
@@ -4596,8 +4597,22 @@ 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.
+	 *
+	 * On Windows, there is no guarantee that we can reserve the memory at
+	 * predefined address due to ASLR, so we retry it multiple times.  Refer
+	 * detailed comments in SubPostmasterMain.
 	 */
-	if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
+	for (i = 0; i < 100; i++)
+	{
+		if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
+			continue;
+		else
+		{
+			shm_reserved = true;
+			break;
+		}
+	}
+	if (!shm_reserved)
 	{
 		/*
 		 * Failed to reserve the memory, so terminate the newly created
@@ -4742,13 +4757,42 @@ SubPostmasterMain(int argc, char *argv[])
 	 * child process's memory map to be different from the parent's, making it
 	 * sometimes impossible to attach to shared memory at the desired address.
 	 * Return the setting to its old value (usually '1' or '2') when finished.
+	 *
+	 * On Windows, there is no guarantee that we can control randomization of
+	 * process's memory map allocation due to ASLR.  To mitigate the impact of
+	 * randomization behavior, we try to attach to the same address multiple
+	 * times (100 retries are completely arbitrary, higher retry count can
+	 * make the user feel like a permanent hang).
 	 */
 	if (strcmp(argv[1], "--forkbackend") == 0 ||
 		strcmp(argv[1], "--forkavlauncher") == 0 ||
 		strcmp(argv[1], "--forkavworker") == 0 ||
 		strcmp(argv[1], "--forkboot") == 0 ||
 		strncmp(argv[1], "--forkbgworker=", 15) == 0)
-		PGSharedMemoryReAttach();
+	{
+		int			i;
+		bool		shm_attached = false;
+
+		for (i = 0; i < 100; i++)
+		{
+			if (!PGSharedMemoryReAttach(i))
+				continue;
+			else
+			{
+				shm_attached = true;
+				break;
+			}
+		}
+
+		if (!shm_attached)
+		{
+			ereport(FATAL,
+			 (errmsg("could not reattach to shared memory (key=%d, addr=%p)",
+					 (int) UsedShmemSegID, UsedShmemSegAddr),
+			  errhint("You can try to start the server again after system restart or disable \
+							 the ASLR.")));
+		}
+	}
 	else
 		PGSharedMemoryNoReAttach();
 
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index a329c81..2a6bb8b 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -60,7 +60,7 @@ extern HANDLE UsedShmemSegID;
 extern void *UsedShmemSegAddr;
 
 #ifdef EXEC_BACKEND
-extern void PGSharedMemoryReAttach(void);
+extern bool PGSharedMemoryReAttach(int retry_count);
 extern void PGSharedMemoryNoReAttach(void);
 #endif
 
