Make the win32 shared memory code try 10 times instead of one if
authorMagnus Hagander
Tue, 5 May 2009 09:48:51 +0000 (09:48 +0000)
committerMagnus Hagander
Tue, 5 May 2009 09:48:51 +0000 (09:48 +0000)
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.

src/backend/port/win32_shmem.c

index 7cb477c6ed07319f490aaf754a6dacac61b53b96..ed485ea80f8bc7e0c803e77b9042802251204c07 100644 (file)
@@ -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);
 
    /*