health_check_timeout did not work correctly. The bug was introduced in
authorYoshiyuki Asaba <y-asaba at pgfoundry.org>
Tue, 26 Feb 2008 01:45:17 +0000 (01:45 +0000)
committerYoshiyuki Asaba <y-asaba at pgfoundry.org>
Tue, 26 Feb 2008 01:45:17 +0000 (01:45 +0000)
V3.4. Report and patch by Kenichi Sawada.

child.c
main.c

diff --git a/child.c b/child.c
index 3e75f0a891e534088d191e916224adbd45c8a2a4..fd2ad1165eb3f8bcee39c8af2018657069ae6cbe 100644 (file)
--- a/child.c
+++ b/child.c
@@ -1174,104 +1174,3 @@ void pool_free_startup_packet(StartupPacket *sp)
                free(sp);
        }
 }
-
-/*
- * check if we can connect to the backend
- * returns 0 for ok. -1 for master down, -2 for secondary down.
- */
-int health_check(void)
-{
-       int fd;
-
-       /* V2 startup packet */
-       typedef struct {
-               int len;                /* startup packet length */
-               StartupPacket_v2 sp;
-       } MySp;
-       MySp mysp;
-       char kind;
-
-       memset(&mysp, 0, sizeof(mysp));
-       mysp.len = htonl(296);
-       mysp.sp.protoVersion = htonl(PROTO_MAJOR_V2 << 16);
-       strcpy(mysp.sp.database, "template1");
-       strncpy(mysp.sp.user, pool_config.health_check_user, sizeof(mysp.sp.user) - 1);
-       *mysp.sp.options = '\0';
-       *mysp.sp.unused = '\0';
-       *mysp.sp.tty = '\0';
-
-       if (*pool_config.current_backend_host_name == '\0')
-               fd = connect_unix_domain_socket(0);
-       else
-               fd = connect_inet_domain_socket(0);
-
-       if (fd < 0)
-       {
-               pool_error("health check failed. master %s at port %d is down",
-                                  pool_config.current_backend_host_name,
-                                  pool_config.current_backend_port);
-               return -1;
-       }
-
-       if (write(fd, &mysp, sizeof(mysp)) < 0)
-       {
-               pool_error("health check failed during write. master %s at port %d is down",
-                                  pool_config.current_backend_host_name,
-                                  pool_config.current_backend_port);
-               close(fd);
-               return -1;
-       }
-
-       read(fd, &kind, 1);
-
-       if (write(fd, "X", 1) < 0)
-       {
-               pool_error("health check failed during write. master %s at port %d is down",
-                                  pool_config.current_backend_host_name,
-                                  pool_config.current_backend_port);
-               close(fd);
-               return -1;
-       }
-
-       close(fd);
-
-       if (!DUAL_MODE)
-               return 0;
-
-       if (*pool_config.secondary_backend_host_name == '\0')
-               fd = connect_unix_domain_socket(1);
-       else
-               fd = connect_inet_domain_socket(1);
-
-       if (fd < 0)
-       {
-               pool_error("health check failed. secondary %s at port %d is down",
-                                  pool_config.secondary_backend_host_name,
-                                  pool_config.secondary_backend_port);
-               return -2;
-       }
-
-       if (write(fd, &mysp, sizeof(mysp)) < 0)
-       {
-               pool_error("health check failed during write. secondary %s at port %d is down",
-                                  pool_config.secondary_backend_host_name,
-                                  pool_config.secondary_backend_port);
-               close(fd);
-               return -2;
-       }
-
-       read(fd, &kind, 1);
-
-       if (write(fd, "X", 1) < 0)
-       {
-               pool_error("health check failed during write. secondary %s at port %d is down",
-                                  pool_config.secondary_backend_host_name,
-                                  pool_config.secondary_backend_port);
-               close(fd);
-               return -2;
-       }
-
-       close(fd);
-
-       return 0;
-}
diff --git a/main.c b/main.c
index 295fa3fc1c304b287c25dc7582b11fa5cffda5b4..cd82c5933b182d52f314994be03ef9118cba49b8 100644 (file)
--- a/main.c
+++ b/main.c
@@ -107,7 +107,7 @@ long int weight_master;     /* normalized weight of master (0-RAND_MAX range) */
 static int stop_sig = SIGTERM; /* stopping signal default value */
 static int switch_over_sig = SIGUSR1;  /* switch over signal default value */
 
-static int health_check_timer_expired;         /* non 0 if health check timer expired */
+static volatile sig_atomic_t health_check_timer_expired;               /* non 0 if health check timer expired */
 static volatile sig_atomic_t failover_request = 0;
 static volatile sig_atomic_t sigchld_request = 0;
 static int pipe_fds[2]; /* for delivering signals */
@@ -360,7 +360,7 @@ int main(int argc, char **argv)
                                /*
                                 * set health checker timeout. we want to detect
                                 * commnuication path failure much earlier before
-                                * TCP/IP statck detects it.
+                                * TCP/IP stack detects it.
                                 */
                                pool_signal(SIGALRM, health_check_timer_handler);
                                alarm(pool_config.health_check_timeout);
@@ -371,7 +371,9 @@ int main(int argc, char **argv)
                         */
                        errno = 0;
                        health_check_timer_expired = 0;
+                       POOL_SETMASK(&UnBlockSig);
                        sts = health_check();
+                       POOL_SETMASK(&BlockSig);
 
                        if (errno != EINTR || (errno == EINTR && health_check_timer_expired))
                        {
@@ -1129,3 +1131,104 @@ static void pool_sleep(unsigned int second)
        }
        POOL_SETMASK(&BlockSig);
 }
+
+/*
+ * check if we can connect to the backend
+ * returns 0 for ok. -1 for master down, -2 for secondary down.
+ */
+int health_check(void)
+{
+       int fd;
+
+       /* V2 startup packet */
+       typedef struct {
+               int len;                /* startup packet length */
+               StartupPacket_v2 sp;
+       } MySp;
+       MySp mysp;
+       char kind;
+
+       memset(&mysp, 0, sizeof(mysp));
+       mysp.len = htonl(296);
+       mysp.sp.protoVersion = htonl(PROTO_MAJOR_V2 << 16);
+       strcpy(mysp.sp.database, "template1");
+       strncpy(mysp.sp.user, pool_config.health_check_user, sizeof(mysp.sp.user) - 1);
+       *mysp.sp.options = '\0';
+       *mysp.sp.unused = '\0';
+       *mysp.sp.tty = '\0';
+
+       if (*pool_config.current_backend_host_name == '\0')
+               fd = connect_unix_domain_socket(0);
+       else
+               fd = connect_inet_domain_socket(0);
+
+       if (fd < 0)
+       {
+               pool_error("health check failed. master %s at port %d is down",
+                                  pool_config.current_backend_host_name,
+                                  pool_config.current_backend_port);
+               return -1;
+       }
+
+       if (write(fd, &mysp, sizeof(mysp)) < 0)
+       {
+               pool_error("health check failed during write. master %s at port %d is down",
+                                  pool_config.current_backend_host_name,
+                                  pool_config.current_backend_port);
+               close(fd);
+               return -1;
+       }
+
+       read(fd, &kind, 1);
+
+       if (write(fd, "X", 1) < 0)
+       {
+               pool_error("health check failed during write. master %s at port %d is down",
+                                  pool_config.current_backend_host_name,
+                                  pool_config.current_backend_port);
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+
+       if (!DUAL_MODE)
+               return 0;
+
+       if (*pool_config.secondary_backend_host_name == '\0')
+               fd = connect_unix_domain_socket(1);
+       else
+               fd = connect_inet_domain_socket(1);
+
+       if (fd < 0)
+       {
+               pool_error("health check failed. secondary %s at port %d is down",
+                                  pool_config.secondary_backend_host_name,
+                                  pool_config.secondary_backend_port);
+               return -2;
+       }
+
+       if (write(fd, &mysp, sizeof(mysp)) < 0)
+       {
+               pool_error("health check failed during write. secondary %s at port %d is down",
+                                  pool_config.secondary_backend_host_name,
+                                  pool_config.secondary_backend_port);
+               close(fd);
+               return -2;
+       }
+
+       read(fd, &kind, 1);
+
+       if (write(fd, "X", 1) < 0)
+       {
+               pool_error("health check failed during write. secondary %s at port %d is down",
+                                  pool_config.secondary_backend_host_name,
+                                  pool_config.secondary_backend_port);
+               close(fd);
+               return -2;
+       }
+
+       close(fd);
+
+       return 0;
+}