From 226afe2f0efb70d6ce986d5f4d97da2f369f69b1 Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Thu, 10 Jan 2019 12:20:07 +0900 Subject: [PATCH] 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; -- 2.39.5