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]