pgpool2.git / summary / log / commit / refs

commit    226afe2f0efb70d6ce986d5f4d97da2f369f69b1
Author:   Tatsuo Ishii <ishii@sraoss.co.jp>
Date:     Thu Jan 10 03:20:07 2019 +0000

    Fix Pgpool child segfault in a race condition.
    
    1) frontend tries to connect to Pgpool-II
    
    2) there's no existing connection cache
    
    3) try to create new backend connections by calling connect_backend()
    
    4) inside connect_backend(), pool_create_cp() gets called
    
    5) pool_create_cp() calls new_connection()
    
    6) failover occurs and the global backend status is set to down, but
       the pgpool main does not send kill signal to the child process yet
    
    7) inside new_connection() after checking VALID_BACKEND, it checks the
       global backend status and finds it is set to down status, so that
       it returns without creating new connection slot
    
    8) connect_backend() continues and accesses the down connection slot
       because local status says it's alive, which results in a segfault.
    
    Since there's already checking for the global status in
    new_connection(), a fix could be syncing the local status with the
    global status there.
    
    See [pgpool-hackers: 3214] for discussion.


src/protocol/pool_connection_pool.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/protocol/pool_connection_pool.c b/src/protocol/pool_connection_pool.c index 6370cb5f8..80d106a15 100644 --- a/src/protocol/pool_connection_pool.c +++ b/src/protocol/pool_connection_pool.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2015 PgPool Global Development Group + * Copyright (c) 2003-2019 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -882,6 +882,9 @@ static POOL_CONNECTION_POOL * new_connection(POOL_CONNECTION_POOL * p) (errmsg("creating new connection to backend"), errdetail("skipping backend slot %d because global backend_status = %d", i, BACKEND_INFO(i).backend_status))); + + /* sync local status with global status */ + *(my_backend_status[i]) = BACKEND_INFO(i).backend_status; continue; } @@ -915,7 +918,7 @@ static POOL_CONNECTION_POOL * new_connection(POOL_CONNECTION_POOL * p) /* set down status to local status area */ *(my_backend_status[i]) = CON_DOWN; - /* if master_node_id is not updated, the update it */ + /* if master_node_id is not updated, then update it */ if (Req_info->master_node_id == i) { int old_master = Req_info->master_node_id; [parent: 93ff97e0b8fe]