pgpool2.git / summary / log / commit / refs

commit    b50642d538dcf98183200005de3367671027f82b
Author:   Yugo Nagata <nagata@sraoss.co.jp>
Date:     Wed Jan 04 05:20:24 2017 +0000

    Fix connection_life_time broken by authentication_timeout
    
    When authentication_timeout is enabled,
    connection_life_time could never be expired, because
    alarm(0) is called at reading start-up packet.
    
    When there only one connection pool is used, this
    problem doesn't occur because the signal handler
    for connection_life_time is always set at the end
    of the session. However, if more than one connection
    pools exist, the handler isn't set but only the time
    to colse the connection is calculated.
    
    To fix it, when authentication_timeout is enabled,
    save the signal handler for conneciont_life_time
    and the remaining time, and undo the handler when
    authentication_timeout is disabled.


src/context/pool_process_context.c | 49 ++++++++++++++++++++++++++++++ src/include/context/pool_process_context.h | 8 +++++ src/protocol/child.c | 6 ++-- src/protocol/pool_connection_pool.c | 6 ++-- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/context/pool_process_context.c b/src/context/pool_process_context.c index cfc2369c6..f29553a56 100644 --- a/src/context/pool_process_context.c +++ b/src/context/pool_process_context.c @@ -52,6 +52,11 @@ void pool_init_process_context(void) process_context->proc_id = my_proc_id; process_context->local_session_id = 0; /* initialize local session counter */ + + process_context->last_alarm_handler = SIG_IGN; + process_context->last_alarm_time = 0; + process_context->last_alarm_second = 0; + process_context->undo_alarm_second = 0; } /* @@ -318,3 +323,47 @@ void pool_coninfo_unset_frontend_connected(int proc_id, int pool_index) con->connected = false; } } + +/* + * Set an alarm clock and a signal handler. + * For pool_alarm_undo(), the alarm second and the old handler + * are saved, and the remaining time is calculated. + */ +void pool_alarm(pool_sighandler_t handler, unsigned int second) +{ + POOL_PROCESS_CONTEXT *p = pool_get_process_context(); + time_t now = time(NULL); + + alarm(second); + p->last_alarm_handler = pool_signal(SIGALRM, handler); + + if (p->last_alarm_second) + { + p->undo_alarm_second = p->last_alarm_second - (now - p->last_alarm_time); + if (p->undo_alarm_second <= 0) + p->undo_alarm_second = 1; + } + + p->last_alarm_time = now; + p->last_alarm_second = second; +} + +/* + * Undo the alarm signal handler using the remaining time. + */ +void pool_undo_alarm() +{ + POOL_PROCESS_CONTEXT *p = pool_get_process_context(); + + if (p->undo_alarm_second) + { + alarm(p->undo_alarm_second); + pool_signal(SIGALRM, p->last_alarm_handler); + p->undo_alarm_second = 0; + } + else + { + alarm(0); + pool_signal(SIGALRM, SIG_IGN); + } +} diff --git a/src/include/context/pool_process_context.h b/src/include/context/pool_process_context.h index 5bdc49819..caab7b19c 100644 --- a/src/include/context/pool_process_context.h +++ b/src/include/context/pool_process_context.h @@ -46,6 +46,11 @@ typedef struct { int local_session_id; /* local session id */ + pool_sighandler_t last_alarm_handler; + time_t last_alarm_time; + unsigned int last_alarm_second; + unsigned int undo_alarm_second; + } POOL_PROCESS_CONTEXT; extern void pool_init_process_context(void); @@ -64,4 +69,7 @@ extern bool pool_is_my_coninfo(ConnectionInfo* connInfo); extern void pool_set_connection_will_be_terminated(ConnectionInfo* connInfo); extern void pool_unset_connection_will_be_terminated(ConnectionInfo* connInfo); +extern void pool_alarm(pool_sighandler_t handler, unsigned int second); +extern void pool_undo_alarm(); + #endif /* POOL_PROCESS_CONTEXT_H */ diff --git a/src/protocol/child.c b/src/protocol/child.c index db5872339..797a97681 100644 --- a/src/protocol/child.c +++ b/src/protocol/child.c @@ -1034,8 +1034,7 @@ static void enable_authentication_timeout(void) { if(pool_config->authentication_timeout <= 0) return; - alarm(pool_config->authentication_timeout); - pool_signal(SIGALRM, authentication_timeout); + pool_alarm(authentication_timeout, pool_config->authentication_timeout); alarm_enabled = true; } @@ -1043,8 +1042,7 @@ static void disable_authentication_timeout(void) { if(alarm_enabled) { - alarm(0); - pool_signal(SIGALRM, SIG_IGN); + pool_undo_alarm(); alarm_enabled = false; } } diff --git a/src/protocol/pool_connection_pool.c b/src/protocol/pool_connection_pool.c index 537ea93bf..289cec488 100644 --- a/src/protocol/pool_connection_pool.c +++ b/src/protocol/pool_connection_pool.c @@ -353,8 +353,7 @@ void pool_connection_pool_timer(POOL_CONNECTION_POOL *backend) (errmsg("setting backend connection close timer"), errdetail("setting alarm after %d seconds", pool_config->connection_life_time))); - pool_signal(SIGALRM, pool_backend_timer_handler); - alarm(pool_config->connection_life_time); + pool_alarm(pool_backend_timer_handler, pool_config->connection_life_time); } /* @@ -444,8 +443,7 @@ void pool_backend_timer(void) nearest = pool_config->connection_life_time - (now - nearest); if (nearest <= 0) nearest = 1; - pool_signal(SIGALRM, pool_backend_timer_handler); - alarm(nearest); + pool_alarm(pool_backend_timer_handler, nearest); } POOL_SETMASK(&UnBlockSig); [parent: 873e2f2eaf2a]