|
13 | 13 | *
|
14 | 14 | *Copyright (c) 2001-2003, PostgreSQL Global Development Group
|
15 | 15 | *
|
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 $ |
17 | 17 | * ----------
|
18 | 18 | */
|
19 | 19 | #include"postgres.h"
|
@@ -191,6 +191,12 @@ pgstat_init(void)
|
191 | 191 | *addr,
|
192 | 192 | hints;
|
193 | 193 | intret;
|
| 194 | +fd_setrset; |
| 195 | +structtimevaltv; |
| 196 | +chartest_byte; |
| 197 | +intsel_res; |
| 198 | + |
| 199 | +#defineTESTBYTEVAL ((char) 199) |
194 | 200 |
|
195 | 201 | /*
|
196 | 202 | * Force start of collector daemon if something to collect
|
@@ -308,6 +314,85 @@ pgstat_init(void)
|
308 | 314 | continue;
|
309 | 315 | }
|
310 | 316 |
|
| 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 | + |
311 | 396 | /* If we get here, we have a working socket */
|
312 | 397 | break;
|
313 | 398 | }
|
|