pgpool2.git / summary / log / commit / refs
commit 9c5ab9831158cd6a38271f8db3bee7a505cdcd0f
Author: Tatsuo Ishii <ishii@sraoss.co.jp>
Date: Wed Jan 26 23:12:09 2022 +0000
Fix pcp_node_info hang when pgpool cannot connect to backend.
Since 4.3 pcp_node_info (and show pool_nodes) try to connect to all
backend to obtain real-time and actual backend status. In certain
cases connect(2) fails and keeps on retrying, and the command does not
complete. To fix this, following modifications are made:
1) db_node_status(), which is responsible for probing backend is alive
or not, tries to connect backend with "connect_timeout" parameter
enabled. The timeout is taken from "connect_timeout" parameter of
pgpool.conf. If connect_timeout in pgpool.conf disabled (i.e. set to
0), the timeout parameter is not set. In this case the command will
not complete.
2) db_node_role(), which is responsible for fetching backend role (primary
or standby), does to not retry in connecting to backend using
make_persistent_db_connection_noerror().
3) inform_node_info(), which is the workhorse of pcp_node_info, tries
to fetch info (thus calling db_node_status() and db_node_role()) only
for specified backend. Before it unconditionally access all backend.
Problem reported and patch reviewed by Emond Papegaaij.
Discussion: https://www.pgpool.net/pipermail/pgpool-general/2022-January/008042.html
src/include/utils/pool_process_reporting.h | 4 ++--
src/pcp_con/pcp_worker.c | 6 ++---
src/utils/pool_process_reporting.c | 37 +++++++++++++++++++++++-------
3 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/src/include/utils/pool_process_reporting.h b/src/include/utils/pool_process_reporting.h
index 511ae72d7..daed4e62d 100644
--- a/src/include/utils/pool_process_reporting.h
+++ b/src/include/utils/pool_process_reporting.h
@@ -6,7 +6,7 @@
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2021 PgPool Global Development Group
+ * Copyright (c) 2003-2022 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -32,7 +32,7 @@ extern void send_complete_and_ready(POOL_CONNECTION * frontend, POOL_CONNECTION_
extern POOL_REPORT_CONFIG * get_config(int *nrows);
extern POOL_REPORT_POOLS * get_pools(int *nrows);
extern POOL_REPORT_PROCESSES * get_processes(int *nrows);
-extern POOL_REPORT_NODES * get_nodes(int *nrows);
+extern POOL_REPORT_NODES * get_nodes(int *nrows, int node_id);
extern POOL_REPORT_VERSION * get_version(void);
extern POOL_HEALTH_CHECK_STATS *get_health_check_stats(int *nrows);
extern POOL_BACKEND_STATS *get_backend_stats(int *nrows);
diff --git a/src/pcp_con/pcp_worker.c b/src/pcp_con/pcp_worker.c
index 832884aef..f15a3878a 100644
--- a/src/pcp_con/pcp_worker.c
+++ b/src/pcp_con/pcp_worker.c
@@ -4,7 +4,7 @@
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2021 PgPool Global Development Group
+ * Copyright (c) 2003-2022 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -854,7 +854,7 @@ inform_node_info(PCP_CONNECTION * frontend, char *buf)
/* Finally, indicate that all data is sent */
char fin_code[] = "CommandComplete";
- nodes = get_nodes(&nrows);
+ nodes = get_nodes(&nrows, node_id);
if (node_id == -1)
{
@@ -887,7 +887,7 @@ inform_node_info(PCP_CONNECTION * frontend, char *buf)
BackendInfo *bi = NULL;
SERVER_ROLE role;
- if (node_id != -1 && node_id != atoi(nodes[i].node_id))
+ if (node_id != -1 && node_id != i)
continue;
bi = pool_get_node_info(i);
diff --git a/src/utils/pool_process_reporting.c b/src/utils/pool_process_reporting.c
index c1df7683f..a085963b5 100644
--- a/src/utils/pool_process_reporting.c
+++ b/src/utils/pool_process_reporting.c
@@ -5,7 +5,7 @@
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2021 PgPool Global Development Group
+ * Copyright (c) 2003-2022 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -1291,9 +1291,10 @@ config_reporting(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
/*
* for SHOW pool_nodes
+ * If node_id is -1, get all node info.
*/
POOL_REPORT_NODES *
-get_nodes(int *nrows)
+get_nodes(int *nrows, int node_id)
{
int i;
POOL_REPORT_NODES *nodes = palloc(NUM_BACKENDS * sizeof(POOL_REPORT_NODES));
@@ -1303,6 +1304,9 @@ get_nodes(int *nrows)
for (i = 0; i < NUM_BACKENDS; i++)
{
+ if (node_id != -1 && node_id != i)
+ continue;
+
bi = pool_get_node_info(i);
snprintf(nodes[i].node_id, POOLCONFIG_MAXIDLEN, "%d", i);
@@ -1319,6 +1323,8 @@ get_nodes(int *nrows)
snprintf(nodes[i].delay, POOLCONFIG_MAXWEIGHTLEN, "%d", 0);
+ snprintf(nodes[i].pg_status, POOLCONFIG_MAXSTATLEN, "%s", db_node_status(i));
+
if (STREAM)
{
if (i == REAL_PRIMARY_NODE_ID)
@@ -1330,7 +1336,15 @@ get_nodes(int *nrows)
snprintf(nodes[i].role, POOLCONFIG_MAXWEIGHTLEN, "%s", "standby");
snprintf(nodes[i].delay, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, bi->standby_delay);
}
- snprintf(nodes[i].pg_role, POOLCONFIG_MAXWEIGHTLEN, "%s", db_node_role(i));
+
+ if (!strcmp(nodes[i].pg_status, "up"))
+ {
+ snprintf(nodes[i].pg_role, POOLCONFIG_MAXWEIGHTLEN, "%s", db_node_role(i));
+ }
+ else
+ {
+ snprintf(nodes[i].pg_role, POOLCONFIG_MAXWEIGHTLEN, "unknown");
+ }
}
else
{
@@ -1342,8 +1356,6 @@ get_nodes(int *nrows)
snprintf(nodes[i].pg_role, POOLCONFIG_MAXWEIGHTLEN, "%s", nodes[i].role);
}
- snprintf(nodes[i].pg_status, POOLCONFIG_MAXSTATLEN, "%s", db_node_status(i));
-
/* status last changed */
localtime_r(&bi->status_changed_time, &tm);
strftime(nodes[i].last_status_change, POOLCONFIG_MAXDATELEN, "%F %T", &tm);
@@ -1390,7 +1402,7 @@ nodes_reporting(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
POOL_REPORT_NODES *nodes;
num_fields = sizeof(field_names) / sizeof(char *);
- nodes = get_nodes(&nrows);
+ nodes = get_nodes(&nrows, -1);
send_row_description_and_data_rows(frontend, backend, num_fields, field_names, offsettbl,
(char *)nodes, sizeof(POOL_REPORT_NODES), nrows);
@@ -2222,7 +2234,8 @@ char *db_node_status(int node)
BackendInfo *bkinfo;
int i;
char portstr[32];
-#define PARAMS_ARRAY_SIZE 7
+ char timeoutstr[32];
+#define PARAMS_ARRAY_SIZE 8
const char *keywords[PARAMS_ARRAY_SIZE];
const char *values[PARAMS_ARRAY_SIZE];
PGPing ret;
@@ -2263,6 +2276,14 @@ char *db_node_status(int node)
values[i] = portstr;
i++;
+ if (pool_config->connect_timeout > 0)
+ {
+ keywords[i] = "connect_timeout";
+ snprintf(timeoutstr, sizeof(timeoutstr), "%d", pool_config->connect_timeout / 1000);
+ values[i] = timeoutstr;
+ i++;
+ }
+
keywords[i] = NULL;
values[i] = NULL;
@@ -2313,7 +2334,7 @@ char *db_node_role(int node)
* Establish connection to backend.
*/
slots[node] = make_persistent_db_connection_noerror(node, host, port, dbname, user,
- password ? password : "", true);
+ password ? password : "", false);
if (slots[node] == NULL)
return "unknown";
[parent: 6b49152fd7ca]