28
28
#include <arpa/inet.h>
29
29
#include <signal.h>
30
30
#include <time.h>
31
- #ifdef HAVE_POLL_H
32
- #include <poll.h>
33
- #endif
34
- #ifdef HAVE_SYS_POLL_H
35
- #include <sys/poll.h>
36
- #endif
37
31
38
32
#include "pgstat.h"
39
33
55
49
#include "storage/backendid.h"
56
50
#include "storage/fd.h"
57
51
#include "storage/ipc.h"
52
+ #include "storage/latch.h"
58
53
#include "storage/pg_shmem.h"
59
54
#include "storage/pmsignal.h"
60
55
#include "storage/procsignal.h"
94
89
* failed statistics collector; in
95
90
* seconds. */
96
91
97
- #define PGSTAT_SELECT_TIMEOUT 2 /* How often to check for postmaster
98
- * death; in seconds. */
99
-
100
92
#define PGSTAT_POLL_LOOP_COUNT (PGSTAT_MAX_WAIT_TIME / PGSTAT_RETRY_DELAY)
101
93
#define PGSTAT_INQ_LOOP_COUNT (PGSTAT_INQ_INTERVAL / PGSTAT_RETRY_DELAY)
102
94
@@ -139,6 +131,8 @@ PgStat_MsgBgWriter BgWriterStats;
139
131
*/
140
132
NON_EXEC_STATIC pgsocket pgStatSock = PGINVALID_SOCKET ;
141
133
134
+ static Latch pgStatLatch ;
135
+
142
136
static struct sockaddr_storage pgStatAddr ;
143
137
144
138
static time_t last_pgstat_start_time ;
@@ -3009,15 +3003,7 @@ PgstatCollectorMain(int argc, char *argv[])
3009
3003
{
3010
3004
int len ;
3011
3005
PgStat_Msg msg ;
3012
-
3013
- #ifndef WIN32
3014
- #ifdef HAVE_POLL
3015
- struct pollfd input_fd ;
3016
- #else
3017
- struct timeval sel_timeout ;
3018
- fd_set rfds ;
3019
- #endif
3020
- #endif
3006
+ int wr ;
3021
3007
3022
3008
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
3023
3009
@@ -3036,9 +3022,13 @@ PgstatCollectorMain(int argc, char *argv[])
3036
3022
elog (FATAL , "setsid() failed: %m" );
3037
3023
#endif
3038
3024
3025
+ /* Initialize private latch for use by signal handlers */
3026
+ InitLatch (& pgStatLatch );
3027
+
3039
3028
/*
3040
3029
* Ignore all signals usually bound to some action in the postmaster,
3041
- * except SIGQUIT.
3030
+ * except SIGHUP and SIGQUIT. Note we don't need a SIGUSR1 handler to
3031
+ * support latch operations, because pgStatLatch is local not shared.
3042
3032
*/
3043
3033
pqsignal (SIGHUP , pgstat_sighup_handler );
3044
3034
pqsignal (SIGINT , SIG_IGN );
@@ -3073,26 +3063,24 @@ PgstatCollectorMain(int argc, char *argv[])
3073
3063
pgStatRunningInCollector = true;
3074
3064
pgStatDBHash = pgstat_read_statsfile (InvalidOid , true);
3075
3065
3076
- /*
3077
- * Setup the descriptor set for select(2). Since only one bit in the set
3078
- * ever changes, we need not repeat FD_ZERO each time.
3079
- */
3080
- #if !defined(HAVE_POLL ) && !defined(WIN32 )
3081
- FD_ZERO (& rfds );
3082
- #endif
3083
-
3084
3066
/*
3085
3067
* Loop to process messages until we get SIGQUIT or detect ungraceful
3086
3068
* death of our parent postmaster.
3087
3069
*
3088
- * For performance reasons, we don't want to do a PostmasterIsAlive() test
3089
- * after every message; instead, do it only when select()/poll() is
3090
- * interrupted by timeout. In essence, we'll stay alive as long as
3091
- * backends keep sending us stuff often, even if the postmaster is gone.
3070
+ * For performance reasons, we don't want to do ResetLatch/WaitLatch after
3071
+ * every message; instead, do that only after a recv() fails to obtain a
3072
+ * message. (This effectively means that if backends are sending us stuff
3073
+ * like mad, we won't notice postmaster death until things slack off a
3074
+ * bit; which seems fine.) To do that, we have an inner loop that
3075
+ * iterates as long as recv() succeeds. We do recognize got_SIGHUP inside
3076
+ * the inner loop, which means that such interrupts will get serviced but
3077
+ * the latch won't get cleared until next time there is a break in the
3078
+ * action.
3092
3079
*/
3093
3080
for (;;)
3094
3081
{
3095
- int got_data ;
3082
+ /* Clear any already-pending wakeups */
3083
+ ResetLatch (& pgStatLatch );
3096
3084
3097
3085
/*
3098
3086
* Quit if we get SIGQUIT from the postmaster.
@@ -3101,87 +3089,37 @@ PgstatCollectorMain(int argc, char *argv[])
3101
3089
break ;
3102
3090
3103
3091
/*
3104
- * Reload configuration if we got SIGHUP from the postmaster.
3105
- */
3106
- if (got_SIGHUP )
3107
- {
3108
- ProcessConfigFile (PGC_SIGHUP );
3109
- got_SIGHUP = false;
3110
- }
3111
-
3112
- /*
3113
- * Write the stats file if a new request has arrived that is not
3114
- * satisfied by existing file.
3115
- */
3116
- if (last_statwrite < last_statrequest )
3117
- pgstat_write_statsfile (false);
3118
-
3119
- /*
3120
- * Wait for a message to arrive; but not for more than
3121
- * PGSTAT_SELECT_TIMEOUT seconds. (This determines how quickly we will
3122
- * shut down after an ungraceful postmaster termination; so it needn't
3123
- * be very fast. However, on some systems SIGQUIT won't interrupt the
3124
- * poll/select call, so this also limits speed of response to SIGQUIT,
3125
- * which is more important.)
3126
- *
3127
- * We use poll(2) if available, otherwise select(2). Win32 has its own
3128
- * implementation.
3129
- */
3130
- #ifndef WIN32
3131
- #ifdef HAVE_POLL
3132
- input_fd .fd = pgStatSock ;
3133
- input_fd .events = POLLIN | POLLERR ;
3134
- input_fd .revents = 0 ;
3135
-
3136
- if (poll (& input_fd , 1 , PGSTAT_SELECT_TIMEOUT * 1000 ) < 0 )
3137
- {
3138
- if (errno == EINTR )
3139
- continue ;
3140
- ereport (ERROR ,
3141
- (errcode_for_socket_access (),
3142
- errmsg ("poll() failed in statistics collector: %m" )));
3143
- }
3144
-
3145
- got_data = (input_fd .revents != 0 );
3146
- #else /* !HAVE_POLL */
3147
-
3148
- FD_SET (pgStatSock , & rfds );
3149
-
3150
- /*
3151
- * timeout struct is modified by select() on some operating systems,
3152
- * so re-fill it each time.
3092
+ * Inner loop iterates as long as we keep getting messages, or until
3093
+ * need_exit becomes set.
3153
3094
*/
3154
- sel_timeout .tv_sec = PGSTAT_SELECT_TIMEOUT ;
3155
- sel_timeout .tv_usec = 0 ;
3156
-
3157
- if (select (pgStatSock + 1 , & rfds , NULL , NULL , & sel_timeout ) < 0 )
3095
+ while (!need_exit )
3158
3096
{
3159
- if (errno == EINTR )
3160
- continue ;
3161
- ereport (ERROR ,
3162
- (errcode_for_socket_access (),
3163
- errmsg ("select() failed in statistics collector: %m" )));
3164
- }
3097
+ /*
3098
+ * Reload configuration if we got SIGHUP from the postmaster.
3099
+ */
3100
+ if (got_SIGHUP )
3101
+ {
3102
+ got_SIGHUP = false;
3103
+ ProcessConfigFile (PGC_SIGHUP );
3104
+ }
3165
3105
3166
- got_data = FD_ISSET ( pgStatSock , & rfds );
3167
- #endif /* HAVE_POLL */
3168
- #else /* WIN32 */
3169
- got_data = pgwin32_waitforsinglesocket ( pgStatSock , FD_READ ,
3170
- PGSTAT_SELECT_TIMEOUT * 1000 );
3171
- #endif
3106
+ /*
3107
+ * Write the stats file if a new request has arrived that is not
3108
+ * satisfied by existing file.
3109
+ */
3110
+ if ( last_statwrite < last_statrequest )
3111
+ pgstat_write_statsfile (false);
3172
3112
3173
- /*
3174
- * If there is a message on the socket, read it and check for
3175
- * validity.
3176
- */
3177
- if (got_data )
3178
- {
3113
+ /*
3114
+ * Try to receive and process a message. This will not block,
3115
+ * since the socket is set to non-blocking mode.
3116
+ */
3179
3117
len = recv (pgStatSock , (char * ) & msg ,
3180
3118
sizeof (PgStat_Msg ), 0 );
3181
3119
if (len < 0 )
3182
3120
{
3183
- if (errno == EINTR )
3184
- continue ;
3121
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR )
3122
+ break ; /* out of inner loop */
3185
3123
ereport (ERROR ,
3186
3124
(errcode_for_socket_access (),
3187
3125
errmsg ("could not read statistics message: %m" )));
@@ -3279,17 +3217,18 @@ PgstatCollectorMain(int argc, char *argv[])
3279
3217
default :
3280
3218
break ;
3281
3219
}
3282
- }
3283
- else
3284
- {
3285
- /*
3286
- * We can only get here if the select/poll timeout elapsed. Check
3287
- * for postmaster death.
3288
- */
3289
- if (!PostmasterIsAlive ())
3290
- break ;
3291
- }
3292
- } /* end of message-processing loop */
3220
+ } /* end of inner message-processing loop */
3221
+
3222
+ /* Sleep until there's something to do */
3223
+ wr = WaitLatchOrSocket (& pgStatLatch ,
3224
+ WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE ,
3225
+ pgStatSock ,
3226
+ -1L );
3227
+
3228
+ /* Check for postmaster death */
3229
+ if (wr & WL_POSTMASTER_DEATH )
3230
+ break ;
3231
+ } /* end of outer loop */
3293
3232
3294
3233
/*
3295
3234
* Save the final stats to reuse at next startup.
@@ -3304,14 +3243,24 @@ PgstatCollectorMain(int argc, char *argv[])
3304
3243
static void
3305
3244
pgstat_exit (SIGNAL_ARGS )
3306
3245
{
3246
+ int save_errno = errno ;
3247
+
3307
3248
need_exit = true;
3249
+ SetLatch (& pgStatLatch );
3250
+
3251
+ errno = save_errno ;
3308
3252
}
3309
3253
3310
3254
/* SIGHUP handler for collector process */
3311
3255
static void
3312
3256
pgstat_sighup_handler (SIGNAL_ARGS )
3313
3257
{
3258
+ int save_errno = errno ;
3259
+
3314
3260
got_SIGHUP = true;
3261
+ SetLatch (& pgStatLatch );
3262
+
3263
+ errno = save_errno ;
3315
3264
}
3316
3265
3317
3266
0 commit comments