summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Hagander2009-02-15 13:58:18 +0000
committerMagnus Hagander2009-02-15 13:58:18 +0000
commit8673a92ef5d2091a7783644a454595c925e24291 (patch)
tree328059fdf8d0646e1af1e4637a2a7bb36a38e516
parentdc7adfd39e298ead3b87711e860b14eb5993a341 (diff)
Loop calling CallNamedPipe() several times in case it fails,
since it can be transient failures, causing kill() to not properly send signals. Original patch from Steve Marshall, modified by me.
-rw-r--r--src/port/kill.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/src/port/kill.c b/src/port/kill.c
index 0b6ee0d2ed..5a2faaa751 100644
--- a/src/port/kill.c
+++ b/src/port/kill.c
@@ -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