Loop calling CallNamedPipe() several times in case it fails,
authorMagnus Hagander
Sun, 15 Feb 2009 13:58:18 +0000 (13:58 +0000)
committerMagnus Hagander
Sun, 15 Feb 2009 13:58:18 +0000 (13:58 +0000)
since it can be transient failures, causing kill() to not
properly send signals.

Original patch from Steve Marshall, modified by me.

src/port/kill.c

index ea71f75c3e93599f6af2e12e570f540e78e41ef8..1ec5ee5b78391611b6a41f14f9dc202e2c53d315 100644 (file)
@@ -9,7 +9,7 @@
  * signals that the backend can recognize.
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/port/kill.c,v 1.11 2009/01/01 17:24:04 momjian Exp $
+ *   $PostgreSQL: pgsql/src/port/kill.c,v 1.12 2009/02/15 13:58:18 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +25,7 @@ pgkill(int pid, int sig)
    BYTE        sigData = sig;
    BYTE        sigRet = 0;
    DWORD       bytes;
+   int         pipe_tries;
 
    /* we allow signal 0 here, but it will be ignored in pg_queue_signal */
    if (sig >= PG_SIGNAL_COUNT || sig < 0)
@@ -39,23 +40,33 @@ pgkill(int pid, int sig)
        return -1;
    }
    snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%u", pid);
-   if (!CallNamedPipe(pipename, &sigData, 1, &sigRet, 1, &bytes, 1000))
-   {
-       if (GetLastError() == ERROR_FILE_NOT_FOUND)
-           errno = ESRCH;
-       else if (GetLastError() == ERROR_ACCESS_DENIED)
-           errno = EPERM;
-       else
-           errno = EINVAL;
-       return -1;
-   }
-   if (bytes != 1 || sigRet != sig)
+
+   /*
+    * Writing data to the named pipe can fail for transient reasons.
+    * Therefore, it is useful to retry if it fails.  The maximum number of
+    * calls to make was empirically determined from a 90-hour notification
+    * stress test.
+    */
+   for (pipe_tries = 0; pipe_tries < 3; pipe_tries++)
    {
-       errno = ESRCH;
-       return -1;
+       if (CallNamedPipe(pipename, &sigData, 1, &sigRet, 1, &bytes, 1000))
+       {
+           if (bytes != 1 || sigRet != sig)
+           {
+               errno = ESRCH;
+               return -1;
+           }
+           return 0;
+       }
    }
 
-   return 0;
+   if (GetLastError() == ERROR_FILE_NOT_FOUND)
+       errno = ESRCH;
+   else if (GetLastError() == ERROR_ACCESS_DENIED)
+       errno = EPERM;
+   else
+       errno = EINVAL;
+   return -1;
 }
 
 #endif