pgpool2.git / summary / log / commit / refs

commit    cdf459f75d234426290e8ed0affc7b1bdc81839e
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Tue Nov 10 05:03:08 2015 +0000

    Change implementation of serialize_accept to flock().
    
    Former implementation uses semaphore. Problem is, when fail over
    happens, pgpool child process exits without releasing semaphore
    lock. There seems no reliable way to fix this. Locking with flock()
    has benefit since the lock held by flock() is automatically released
    before exiting the process. The lock file will be created as
    "logdir/accept_lock".


src/include/pool.h | 3 +-- src/protocol/child.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/include/pool.h b/src/include/pool.h index 82761d98e..aeee13cf8 100644 --- a/src/include/pool.h +++ b/src/include/pool.h @@ -360,13 +360,12 @@ extern int my_master_node_id; #define NO_LOAD_BALANCE "/*NO LOAD BALANCE*/" #define NO_LOAD_BALANCE_COMMENT_SZ (sizeof(NO_LOAD_BALANCE)-1) -#define MAX_NUM_SEMAPHORES 6 +#define MAX_NUM_SEMAPHORES 5 #define CONN_COUNTER_SEM 0 #define REQUEST_INFO_SEM 1 #define SHM_CACHE_SEM 2 #define QUERY_CACHE_STATS_SEM 3 #define PCP_REQUEST_SEM 4 -#define ACCEPT_FD_SEM 5 #define MAX_REQUEST_QUEUE_SIZE 10 #define MAX_SEC_WAIT_FOR_CLUSTER_TRANSATION 6 /*number of sec to wait for watchdog command if cluster is stabalizing */ diff --git a/src/protocol/child.c b/src/protocol/child.c index 8bcc5f829..b5c59dd8e 100644 --- a/src/protocol/child.c +++ b/src/protocol/child.c @@ -43,6 +43,7 @@ #include <unistd.h> #include <stdlib.h> #include <sys/time.h> +#include <sys/file.h> #ifdef HAVE_CRYPT_H #include <crypt.h> @@ -90,6 +91,9 @@ static bool backend_cleanup(POOL_CONNECTION* volatile *frontend, POOL_CONNECTION static void free_persisten_db_connection_memory(POOL_CONNECTION_POOL_SLOT *cp); static int choose_db_node_id(char *str); static void child_will_go_down(int code, Datum arg); +static void accept_lock(void); +static void accept_unlock(void); + /* * non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived */ @@ -116,6 +120,8 @@ char remote_host[NI_MAXHOST]; /* client host */ char remote_port[NI_MAXSERV]; /* client port */ POOL_CONNECTION* volatile child_frontend = NULL; +static int accept_lock_fd; + /* * child main loop */ @@ -1838,7 +1844,7 @@ wait_for_new_connections(int *fds, struct timeval *timeout, SockAddr *saddr) */ if (pool_config->child_life_time == 0 && pool_config->serialize_accept != 0) { - pool_semaphore_lock(ACCEPT_FD_SEM); + accept_lock(); ereport(DEBUG1, (errmsg("LOCKING select()"))); } @@ -1849,7 +1855,7 @@ wait_for_new_connections(int *fds, struct timeval *timeout, SockAddr *saddr) if (pool_config->child_life_time == 0 && pool_config->serialize_accept != 0) { - pool_semaphore_unlock(ACCEPT_FD_SEM); + accept_unlock(); ereport(DEBUG1, (errmsg("UNLOCKING select()"))); } @@ -2351,3 +2357,51 @@ int pg_frontend_exists(void) return -1; return 0; } + +/* + * Aquire accept lock. Lock file is created as + * pool_config->logdir/accept_lock. + */ +static void accept_lock(void) +{ + if (!accept_lock_fd) + { + char path[1024]; + + snprintf(path, sizeof(path), "%s/accept_lock", pool_config->logdir); + accept_lock_fd = open(path, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); + if (accept_lock_fd == -1) + { + ereport(WARNING, + (errmsg("failed to open accept_lock.reason: %s", strerror(errno)))); + return; + } + } + + if (flock(accept_lock_fd, LOCK_EX) == -1) + { + ereport(WARNING, + (errmsg("failed to lock accept_lock.reason: %s", strerror(errno)))); + return; + } +} + +/* + * Release accept lock + */ +static void accept_unlock(void) +{ + if (!accept_lock_fd) + { + ereport(WARNING, + (errmsg("accept_lock_fd is not open"))); + return; + } + + if (flock(accept_lock_fd, LOCK_UN) == -1) + { + ereport(WARNING, + (errmsg("failed to unlock accept_lock.reason: %s", strerror(errno)))); + return; + } +} [parent: 3242ab4073d0]