aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-07-16 18:17:14 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-07-16 18:17:14 +0000
commite96373aae58f0e12a4c1845d5c10d94729a01b52 (patch)
tree277534c18f20b509bf86ea54912ace6605d6cd5a
parenta420818d679a88a18cc206f6f9d353587840dbc3 (diff)
downloadpostgresql-e96373aae58f0e12a4c1845d5c10d94729a01b52.tar.gz
postgresql-e96373aae58f0e12a4c1845d5c10d94729a01b52.zip
Ensure that we retry rather than erroring out when send() or recv() return
EINTR; the stats code was failing to do this and so were a couple of places in the postmaster. The stats code assumed that recv() could not return EINTR if a preceding select() showed the socket to be read-ready, but this is demonstrably false with our Windows implementation of recv(), and it may not be the case on all Unix variants either. I think this explains the intermittent stats regression test failures we've been seeing, as well as reports of stats collector instability under high load on Windows. Backpatch as far as 8.0.
-rw-r--r--src/backend/postmaster/pgstat.c27
-rw-r--r--src/backend/postmaster/postmaster.c13
2 files changed, 33 insertions, 7 deletions
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index ac51d2bab7b..c971c06704a 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
*
* Copyright (c) 2001-2006, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.135 2006/07/14 14:52:22 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.136 2006/07/16 18:17:14 tgl Exp $
* ----------
*/
#include "postgres.h"
@@ -323,8 +323,12 @@ pgstat_init(void)
* rules prevent it).
*/
test_byte = TESTBYTEVAL;
+
+retry1:
if (send(pgStatSock, &test_byte, 1, 0) != 1)
{
+ if (errno == EINTR)
+ goto retry1; /* if interrupted, just retry */
ereport(LOG,
(errcode_for_socket_access(),
errmsg("could not send test message on socket for statistics collector: %m")));
@@ -375,8 +379,11 @@ pgstat_init(void)
test_byte++; /* just make sure variable is changed */
+retry2:
if (recv(pgStatSock, &test_byte, 1, 0) != 1)
{
+ if (errno == EINTR)
+ goto retry2; /* if interrupted, just retry */
ereport(LOG,
(errcode_for_socket_access(),
errmsg("could not receive test message on socket for statistics collector: %m")));
@@ -1533,17 +1540,23 @@ pgstat_setheader(PgStat_MsgHdr *hdr, StatMsgType mtype)
static void
pgstat_send(void *msg, int len)
{
+ int rc;
+
if (pgStatSock < 0)
return;
((PgStat_MsgHdr *) msg)->m_size = len;
+ /* We'll retry after EINTR, but ignore all other failures */
+ do
+ {
+ rc = send(pgStatSock, msg, len, 0);
+ } while (rc < 0 && errno == EINTR);
+
#ifdef USE_ASSERT_CHECKING
- if (send(pgStatSock, msg, len, 0) < 0)
+ /* In debug builds, log send failures ... */
+ if (rc < 0)
elog(LOG, "could not send to statistics collector: %m");
-#else
- send(pgStatSock, msg, len, 0);
- /* We deliberately ignore any error from send() */
#endif
}
@@ -1718,9 +1731,13 @@ PgstatCollectorMain(int argc, char *argv[])
len = recv(pgStatSock, (char *) &msg,
sizeof(PgStat_Msg), 0);
if (len < 0)
+ {
+ if (errno == EINTR)
+ continue;
ereport(ERROR,
(errcode_for_socket_access(),
errmsg("could not read statistics message: %m")));
+ }
/*
* We ignore messages that are smaller than our common header
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index aa0f4e3418c..6c8cf982ce6 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.494 2006/07/15 15:47:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.495 2006/07/16 18:17:14 tgl Exp $
*
* NOTES
*
@@ -1374,8 +1374,12 @@ ProcessStartupPacket(Port *port, bool SSLdone)
#else
SSLok = 'N'; /* No support for SSL */
#endif
+
+retry1:
if (send(port->sock, &SSLok, 1, 0) != 1)
{
+ if (errno == EINTR)
+ goto retry1; /* if interrupted, just retry */
ereport(COMMERROR,
(errcode_for_socket_access(),
errmsg("failed to send SSL negotiation response: %m")));
@@ -2524,6 +2528,7 @@ static void
report_fork_failure_to_client(Port *port, int errnum)
{
char buffer[1000];
+ int rc;
/* Format the error message packet (always V2 protocol) */
snprintf(buffer, sizeof(buffer), "E%s%s\n",
@@ -2534,7 +2539,11 @@ report_fork_failure_to_client(Port *port, int errnum)
if (!pg_set_noblock(port->sock))
return;
- send(port->sock, buffer, strlen(buffer) + 1, 0);
+ /* We'll retry after EINTR, but ignore all other failures */
+ do
+ {
+ rc = send(port->sock, buffer, strlen(buffer) + 1, 0);
+ } while (rc < 0 && errno == EINTR);
}