From: Yoshiyuki Asaba Date: Tue, 26 Feb 2008 01:45:17 +0000 (+0000) Subject: health_check_timeout did not work correctly. The bug was introduced in X-Git-Url: http://git.postgresql.org/gitweb/edit?a=commitdiff_plain;h=f2c4e2e21e9566891e340ff896c2993474710e3f;p=pgpool1.git health_check_timeout did not work correctly. The bug was introduced in V3.4. Report and patch by Kenichi Sawada. --- diff --git a/child.c b/child.c index 3e75f0a..fd2ad11 100644 --- 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 295fa3f..cd82c59 100644 --- 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; +}