Fix a posible hang during health checking V3_1_STABLE
authorYugo Nagata <nagata@sraoss.co.jp>
Wed, 15 Jun 2016 06:24:21 +0000 (15:24 +0900)
committerYugo Nagata <nagata@sraoss.co.jp>
Mon, 3 Jul 2017 05:35:59 +0000 (14:35 +0900)
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

main.c
pool.h
pool_process_query.c

diff --git a/main.c b/main.c
index a32afaec2a222685aa3c8bb890043026144f1e31..f7de0ac2c590984360ba4d31c78ca465d26c28dc 100644 (file)
--- 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 8107b5c5526578a5294c88f07b91fa5aa1685911..c3fb39bdbb81cc2e87d2a30cf7c5609f47e752ce 100644 (file)
--- 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 */
index fd815b9980666704ca4bdc9f02575ff4fd5fcab2..27fbc4d558b9369992ce31c07e7d97394de643dc 100644 (file)
@@ -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;