From: Magnus Hagander <magnus@hagander.net>
Date: Tue, 5 May 2009 09:48:51 +0000 (+0000)
Subject: Make the win32 shared memory code try 10 times instead of one if
X-Git-Tag: REL8_4_BETA2~42
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5d540add340040373364cec82caa288e6cc22533;p=postgresql

Make the win32 shared memory code try 10 times instead of one if
it fails because the shared memory segment already exists. This
means it can take up to 10 seconds before it reports the error
if it *does* exist, but hopefully it will make the system capable
of restarting even when the server is under high load.
---

diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
index 7cb477c6ed..ed485ea80f 100644
--- a/src/backend/port/win32_shmem.c
+++ b/src/backend/port/win32_shmem.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/port/win32_shmem.c,v 1.8 2009/05/04 08:36:40 mha Exp $
+ *	  $PostgreSQL: pgsql/src/backend/port/win32_shmem.c,v 1.9 2009/05/05 09:48:51 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -123,6 +123,7 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
 	HANDLE		hmap,
 				hmap2;
 	char	   *szShareMem;
+	int			i;
 
 	/* Room for a header? */
 	Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
@@ -131,54 +132,53 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
 
 	UsedShmemSegAddr = NULL;
 
-	/* In case CreateFileMapping() doesn't set the error code to 0 on success */
-	SetLastError(0);
-
-	hmap = CreateFileMapping((HANDLE) 0xFFFFFFFF,		/* Use the pagefile */
-							 NULL,		/* Default security attrs */
-							 PAGE_READWRITE,	/* Memory is Read/Write */
-							 0L,	/* Size Upper 32 Bits	*/
-							 (DWORD) size,		/* Size Lower 32 bits */
-							 szShareMem);
-
-	if (!hmap)
-		ereport(FATAL,
-				(errmsg("could not create shared memory segment: %lu", GetLastError()),
-				 errdetail("Failed system call was CreateFileMapping(size=%lu, name=%s).",
-						   (unsigned long) size, szShareMem)));
-
 	/*
-	 * If the segment already existed, CreateFileMapping() will return a
-	 * handle to the existing one.
+	 * When recycling a shared memory segment, it may take a short while
+	 * before it gets dropped from the global namespace. So re-try after
+	 * sleeping for a second, and continue retrying 10 times.
+	 * (both the 1 second time and the 10 retries are completely arbitrary)
 	 */
-	if (GetLastError() == ERROR_ALREADY_EXISTS)
+	for (i = 0; i < 10; i++)
 	{
-		/*
-		 * When recycling a shared memory segment, it may take a short while
-		 * before it gets dropped from the global namespace. So re-try after
-		 * sleeping for a second.
-		 */
-		CloseHandle(hmap);		/* Close the old handle, since we got a valid
-								 * one to the previous segment. */
-
-		Sleep(1000);
-
 		/* In case CreateFileMapping() doesn't set the error code to 0 on success */
 		SetLastError(0);
 
-		hmap = CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0L, (DWORD) size, szShareMem);
+		hmap = CreateFileMapping((HANDLE) 0xFFFFFFFF,		/* Use the pagefile */
+								 NULL,		/* Default security attrs */
+								 PAGE_READWRITE,	/* Memory is Read/Write */
+								 0L,	/* Size Upper 32 Bits	*/
+								 (DWORD) size,		/* Size Lower 32 bits */
+								 szShareMem);
+
 		if (!hmap)
 			ereport(FATAL,
 					(errmsg("could not create shared memory segment: %lu", GetLastError()),
 					 errdetail("Failed system call was CreateFileMapping(size=%lu, name=%s).",
 							   (unsigned long) size, szShareMem)));
 
+		/*
+		 * If the segment already existed, CreateFileMapping() will return a
+		 * handle to the existing one.
+		 */
 		if (GetLastError() == ERROR_ALREADY_EXISTS)
-			ereport(FATAL,
-				 (errmsg("pre-existing shared memory block is still in use"),
-				  errhint("Check if there are any old server processes still running, and terminate them.")));
+		{
+			CloseHandle(hmap);		/* Close the old handle, since we got a valid
+									 * one to the previous segment. */
+			Sleep(1000);
+			continue;
+		}
+		break;
 	}
 
+	/*
+	 * If the last call in the loop still returned ERROR_ALREADY_EXISTS, this shared memory
+	 * segment exists and we assume it belongs to somebody else.
+	 */
+	if (GetLastError() == ERROR_ALREADY_EXISTS)
+		ereport(FATAL,
+			 (errmsg("pre-existing shared memory block is still in use"),
+			  errhint("Check if there are any old server processes still running, and terminate them.")));
+
 	free(szShareMem);
 
 	/*