提交 e96373aa 编写于 作者: T Tom Lane

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.
上级 a420818d
......@@ -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
......
......@@ -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);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册