pgpool2.git / summary / log / commit / refs
commit 9022ff842fb5dbbe06e2f2f4cf38fadf47b592da
Author: Tatsuo Ishii <ishii@postgresql.org>
Date: Mon Jan 29 04:04:58 2018 +0000
Fix pgpool child process segfault when ALWAYS_MASTER is on.
If following conditions are all met pgpool child segfaults:
1) Streaming replication mode.
2) fail_over_on_backend_error is off.
3) ALWAYS_MASTER flags is set to the master (writer) node.
4) pgpool_status file indicates that the node mentioned in #3 is in
down status.
What happens here is,
1) find_primary_node() returns node id 0 without checking the status
of node 0 since ALWAYS_MASTER is set. It's remembered as the
primary node id. The node id is stored in Req_info->primary_node_id.
2) The connection to backend 0 is not created since pgpool_status says
it's in down status.
3) upon starting of session, select_load_balancing_node () is called
and it tries to determine the database name from client's start up
packet.
4) Since MASTER_CONNECTION macro points to the PRIMARY_NODE,
MASTER_CONNECTION(ses->backend) is NULL and it results in a segfault.
The fix I propose is, to change PRIMARY_NODE_ID macro so that it
returns REAL_MASTER_NODE_ID (that is the youngest node id which is
alive) if the node id in Req_info->primary_node_id is in down status.
So we have the "true" primary node id in Req_info->primary_node_id,
and "fake" primary node id returned by PRIMARY_NODE_ID macro.
See [pgpool-hackers: 2687] and [pgpool-general: 5881] Pgpool-3.7.1
segmentation fault for more details.
Since ALWAYS_MASTER flag was introduced in 3.7, back pached to 3.7
only.
Per bug report from Philip Champon.
src/include/pool.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/include/pool.h b/src/include/pool.h
index 48cd82909..16d03a475 100644
--- a/src/include/pool.h
+++ b/src/include/pool.h
@@ -333,7 +333,7 @@ extern int my_master_node_id;
* mode or there's no primary node, this macro returns
* REAL_MASTER_NODE_ID.
*/
-#define PRIMARY_NODE_ID (Req_info->primary_node_id >=0?\
+#define PRIMARY_NODE_ID (Req_info->primary_node_id >=0 && VALID_BACKEND(Req_info->primary_node_id) ? \
Req_info->primary_node_id:REAL_MASTER_NODE_ID)
#define IS_PRIMARY_NODE_ID(node_id) (node_id == PRIMARY_NODE_ID)
[parent: e6b4a1ec58ee]