From: Yugo Nagata Date: Wed, 15 Jun 2016 06:24:21 +0000 (+0900) Subject: Fix a posible hang during health checking X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=refs%2Fheads%2FV3_1_STABLE;p=pgpool2.git Fix a posible hang during health checking Helath checking was hang when any data wasn't sent from backend after connect(2) succeeded. To fix this, pool_check_fd() returns 1 when select(2) exits with EINTR due to SIGALRM while health checkking is performed. Reported and patch provided by harukat and some modification by Yugo. Per bug #204. backported from 3.4 or later; https://git.postgresql.org/gitweb/?p=pgpool2.git;a=commitdiff;h=ed9f2900f1b611f5cfd52e8f758c3616861e60c0 --- diff --git a/main.c b/main.c index a32afaec2..f7de0ac2c 100644 --- a/main.c +++ b/main.c @@ -162,7 +162,7 @@ static int not_detach = 0; /* non 0 if non detach option (-n) is given */ static int stop_sig = SIGTERM; /* stopping signal default value */ -static volatile sig_atomic_t health_check_timer_expired; /* non 0 if health check timer expired */ +volatile sig_atomic_t health_check_timer_expired; /* non 0 if health check timer expired */ POOL_REQUEST_INFO *Req_info; /* request info area in shared memory */ volatile sig_atomic_t *InRecovery; /* non 0 if recovery is started */ diff --git a/pool.h b/pool.h index 8107b5c55..c3fb39bdb 100644 --- a/pool.h +++ b/pool.h @@ -397,6 +397,7 @@ extern bool run_as_pcp_child; extern POOL_CONNECTION_POOL *pool_connection_pool; /* connection pool */ extern volatile sig_atomic_t backend_timer_expired; /* flag for connection closed timer is expired */ +extern volatile sig_atomic_t health_check_timer_expired; /* non 0 if health check timer expired */ extern long int weight_master; /* normalized weight of master (0-RAND_MAX range) */ extern int my_proc_id; /* process table id (!= UNIX's PID) */ extern POOL_SYSTEMDB_CONNECTION_POOL *system_db_info; /* systemdb */ diff --git a/pool_process_query.c b/pool_process_query.c index fd815b998..27fbc4d55 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -1054,6 +1054,7 @@ int pool_check_fd(POOL_CONNECTION *cp) int fds; struct timeval timeout; struct timeval *timeoutp; + int save_errno; /* * If SSL is enabled, we need to check SSL internal buffer @@ -1083,8 +1084,15 @@ int pool_check_fd(POOL_CONNECTION *cp) FD_SET(fd, &exceptmask); fds = select(fd+1, &readmask, NULL, &exceptmask, timeoutp); + save_errno = errno; if (fds == -1) { + if (health_check_timer_expired && errno == EINTR) + { + pool_error("health check timed out while waiting for reading data"); + errno = save_errno; + return 1; + } if (errno == EAGAIN || errno == EINTR) continue;