Skip to content

Commit 0d88dd1

Browse files
committed
Before deciding we can use a socket for statistics collection, test to
ensure that it actually passes data. This catches cases such as a kernel packet filter rule that makes the socket useless. Andrew Dunstan
1 parent 6b198d6 commit 0d88dd1

File tree

1 file changed

+86
-1
lines changed

1 file changed

+86
-1
lines changed

src/backend/postmaster/pgstat.c

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
* Copyright (c) 2001-2003, PostgreSQL Global Development Group
1515
*
16-
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.61 2004/03/15 16:21:37 momjian Exp $
16+
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.62 2004/03/22 23:55:29 tgl Exp $
1717
* ----------
1818
*/
1919
#include "postgres.h"
@@ -191,6 +191,12 @@ pgstat_init(void)
191191
*addr,
192192
hints;
193193
int ret;
194+
fd_set rset;
195+
struct timeval tv;
196+
char test_byte;
197+
int sel_res;
198+
199+
#define TESTBYTEVAL ((char) 199)
194200

195201
/*
196202
* Force start of collector daemon if something to collect
@@ -308,6 +314,85 @@ pgstat_init(void)
308314
continue;
309315
}
310316

317+
/*
318+
* Try to send and receive a one-byte test message on the socket.
319+
* This is to catch situations where the socket can be created but
320+
* will not actually pass data (for instance, because kernel packet
321+
* filtering rules prevent it).
322+
*/
323+
test_byte = TESTBYTEVAL;
324+
if (send(pgStatSock, &test_byte, 1, 0) != 1)
325+
{
326+
ereport(LOG,
327+
(errcode_for_socket_access(),
328+
errmsg("could not send test message on socket for statistics collector: %m")));
329+
closesocket(pgStatSock);
330+
pgStatSock = -1;
331+
continue;
332+
}
333+
334+
/*
335+
* There could possibly be a little delay before the message can be
336+
* received. We arbitrarily allow up to half a second before deciding
337+
* it's broken.
338+
*/
339+
for (;;) /* need a loop to handle EINTR */
340+
{
341+
FD_ZERO(&rset);
342+
FD_SET(pgStatSock, &rset);
343+
tv.tv_sec = 0;
344+
tv.tv_usec = 500000;
345+
sel_res = select(pgStatSock+1, &rset, NULL, NULL, &tv);
346+
if (sel_res >= 0 || errno != EINTR)
347+
break;
348+
}
349+
if (sel_res < 0)
350+
{
351+
ereport(LOG,
352+
(errcode_for_socket_access(),
353+
errmsg("select() failed in statistics collector: %m")));
354+
closesocket(pgStatSock);
355+
pgStatSock = -1;
356+
continue;
357+
}
358+
if (sel_res == 0 || !FD_ISSET(pgStatSock, &rset))
359+
{
360+
/*
361+
* This is the case we actually think is likely, so take pains to
362+
* give a specific message for it.
363+
*
364+
* errno will not be set meaningfully here, so don't use it.
365+
*/
366+
ereport(LOG,
367+
(ERRCODE_CONNECTION_FAILURE,
368+
errmsg("test message did not get through on socket for statistics collector")));
369+
closesocket(pgStatSock);
370+
pgStatSock = -1;
371+
continue;
372+
}
373+
374+
test_byte++; /* just make sure variable is changed */
375+
376+
if (recv(pgStatSock, &test_byte, 1, 0) != 1)
377+
{
378+
ereport(LOG,
379+
(errcode_for_socket_access(),
380+
errmsg("could not receive test message on socket for statistics collector: %m")));
381+
closesocket(pgStatSock);
382+
pgStatSock = -1;
383+
continue;
384+
}
385+
386+
if (test_byte != TESTBYTEVAL) /* strictly paranoia ... */
387+
{
388+
ereport(LOG,
389+
(ERRCODE_INTERNAL_ERROR,
390+
errmsg("incorrect test message transmission on socket for statistics collector")));
391+
closesocket(pgStatSock);
392+
pgStatSock = -1;
393+
continue;
394+
}
395+
311396
/* If we get here, we have a working socket */
312397
break;
313398
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy