pgpool2.git / summary / log / commit / refs
commit ab3d0ea047e0c2afe01090141da7d4e828cedb51
Author: Tatsuo Ishii <ishii at sraoss.co.jp>
Date: Tue Aug 23 04:36:57 2011 +0000
Fix segfault in following scenario:
- Add new node in pgpool.conf.
- Reload pgpool.conf. At this point new is in down status.
- Connect using psql and do some query.
- Failback the new node.
- Do another query and pgpool child segfaults.
- Worker child segfaults
To fix this,
- Initialize private_backend_status with MAX_NUM_BACKENDS, rather than
NUM_BACKENDS.
- Add signal handler to worker process and pcp child process. When a
failback event occurs, pgpool main sends SIGUSR1 to those processes.
- Those processes set restart request flag and restart whenever
convenient.
Fix suggested by Gurjeet Singh.
child.c | 21 ++++++++-------------
main.c | 19 ++++++++++++++++++-
pcp_child.c | 24 +++++++++++++++++++++++-
pool.h | 3 +++
pool_worker_child.c | 17 ++++++++++++++++-
5 files changed, 68 insertions(+), 16 deletions(-)
diff --git a/child.c b/child.c
index b9e62bb69..2aacea4e9 100644
--- a/child.c
+++ b/child.c
@@ -74,8 +74,6 @@ static void init_system_db_connection(void);
static bool connect_using_existing_connection(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend,
StartupPacket *sp);
-static void initialize_private_backend_status(void);
-
/*
* non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived
*/
@@ -91,11 +89,6 @@ char remote_ps_data[NI_MAXHOST]; /* used for set_ps_display */
volatile sig_atomic_t got_sighup = 0;
-/*
- * Private copy of backend status
- */
-static BACKEND_STATUS private_backend_status[MAX_NUM_BACKENDS];
-
/*
* child main loop
*/
@@ -137,7 +130,7 @@ void do_child(int unix_fd, int inet_fd)
#endif
/* Initialize my backend status */
- initialize_private_backend_status();
+ pool_initialize_private_backend_status();
/* Initialize per process context */
pool_init_process_context();
@@ -273,15 +266,15 @@ void do_child(int unix_fd, int inet_fd)
*/
/* Check if restart request is set because of failback event
- * happend. If so, exit myself with exit code 1 to be
- * restarted by pgpool parent.
+ * happend. If so, close idle connections to backend and make
+ * a new copy of backend status.
*/
if (pool_get_my_process_info()->need_to_restart)
{
pool_log("do_child: failback event found. discard existing connections");
pool_get_my_process_info()->need_to_restart = 0;
close_idle_connection(0);
- initialize_private_backend_status();
+ pool_initialize_private_backend_status();
}
/*
@@ -1961,11 +1954,13 @@ static void init_system_db_connection(void)
* We copy the backend status to private area so that
* they are not changed while I am alive.
*/
-static void initialize_private_backend_status(void)
+void pool_initialize_private_backend_status(void)
{
int i;
- for (i=0;i<NUM_BACKENDS;i++)
+ pool_debug("pool_initialize_private_backend_status: initialize backend status");
+
+ for (i=0;i<MAX_NUM_BACKENDS;i++)
{
private_backend_status[i] = BACKEND_INFO(i).backend_status;
/* my_backend_status is referred to by VALID_BACKEND macro. */
diff --git a/main.c b/main.c
index b1164d193..a90121b05 100644
--- a/main.c
+++ b/main.c
@@ -130,6 +130,11 @@ static struct sockaddr_un pcp_un_addr; /* unix domain socket path for PCP */
ProcessInfo *process_info; /* Per child info table on shmem */
+/*
+ * Private copy of backend status
+ */
+BACKEND_STATUS private_backend_status[MAX_NUM_BACKENDS];
+
/*
* shmem connection info table
* this is a three dimension array. i.e.:
@@ -510,7 +515,7 @@ int main(int argc, char **argv)
* (get_next_master_node() uses VALID_BACKEND)
*/
- for (i=0;i<NUM_BACKENDS;i++)
+ for (i=0;i<MAX_NUM_BACKENDS;i++)
{
my_backend_status[i] = &(BACKEND_INFO(i).backend_status);
}
@@ -1798,6 +1803,11 @@ static void failover(void)
{
process_info[i].need_to_restart = 1;
}
+
+ /*
+ * Send restart request to worker child.
+ */
+ kill(worker_pid, SIGUSR1);
}
if (Req_info->kind == NODE_UP_REQUEST)
@@ -1826,6 +1836,13 @@ static void failover(void)
* failover/failback done
*/
kill(pcp_pid, SIGUSR2);
+
+ sleep(1);
+
+ /*
+ * Send restart request to pcp child.
+ */
+ kill(pcp_pid, SIGUSR1);
}
/*
diff --git a/pcp_child.c b/pcp_child.c
index 6a3eb3f4c..621cbf93f 100644
--- a/pcp_child.c
+++ b/pcp_child.c
@@ -69,6 +69,7 @@ static void unset_nonblock(int fd);
static int user_authenticate(char *buf, char *passwd_file, char *salt, int salt_len);
static RETSIGTYPE wakeup_handler(int sig);
static RETSIGTYPE reload_config_handler(int sig);
+static RETSIGTYPE restart_handler(int sig);
static int pool_detach_node(int node_id, bool gracefully);
static int pool_promote_node(int node_id, bool gracefully);
@@ -77,6 +78,16 @@ extern char **myargv;
static volatile sig_atomic_t pcp_got_sighup = 0;
volatile sig_atomic_t pcp_wakeup_request = 0;
+static volatile sig_atomic_t pcp_restart_request = 0;
+
+#define CHECK_RESTART_REQUEST \
+ do { \
+ if (pcp_restart_request) \
+ { \
+ pool_log("pcp child process received restart request"); \
+ exit(1); \
+ } \
+ } while (0)
void
pcp_do_child(int unix_fd, int inet_fd, char *pcp_conf_file)
@@ -108,11 +119,14 @@ pcp_do_child(int unix_fd, int inet_fd, char *pcp_conf_file)
signal(SIGHUP, reload_config_handler);
signal(SIGQUIT, die);
signal(SIGCHLD, SIG_DFL);
- signal(SIGUSR1, SIG_DFL);
+ signal(SIGUSR1, restart_handler);
signal(SIGUSR2, wakeup_handler);
signal(SIGPIPE, SIG_IGN);
signal(SIGALRM, SIG_IGN);
+ /* Initialize my backend status */
+ pool_initialize_private_backend_status();
+
/* Initialize process context */
pool_init_process_context();
@@ -120,6 +134,8 @@ pcp_do_child(int unix_fd, int inet_fd, char *pcp_conf_file)
{
errno = 0;
+ CHECK_RESTART_REQUEST;
+
if (frontend == NULL)
{
frontend = pcp_do_accept(unix_fd, inet_fd);
@@ -1056,6 +1072,12 @@ wakeup_handler(int sig)
pcp_wakeup_request = 1;
}
+static RETSIGTYPE
+restart_handler(int sig)
+{
+ pcp_restart_request = 1;
+}
+
static PCP_CONNECTION *
pcp_do_accept(int unix_fd, int inet_fd)
{
diff --git a/pool.h b/pool.h
index 05201c368..6ea09df9e 100644
--- a/pool.h
+++ b/pool.h
@@ -407,6 +407,8 @@ extern volatile sig_atomic_t exit_request;
#define QUERY_STRING_BUFFER_LEN 1024
extern char query_string_buffer[]; /* last query string sent to simpleQuery() */
+extern BACKEND_STATUS private_backend_status[MAX_NUM_BACKENDS];
+
/*
* public functions
*/
@@ -569,6 +571,7 @@ extern int wait_connection_closed(void);
/* child.c */
extern void cancel_request(CancelPacket *sp);
extern void check_stop_request(void);
+extern void pool_initialize_private_backend_status(void);
/* pool_process_query.c */
extern void reset_variables(void);
diff --git a/pool_worker_child.c b/pool_worker_child.c
index eade54338..0d084f373 100644
--- a/pool_worker_child.c
+++ b/pool_worker_child.c
@@ -63,6 +63,7 @@ extern char **myargv;
char remote_ps_data[NI_MAXHOST]; /* used for set_ps_display */
static POOL_CONNECTION_POOL_SLOT *slots[MAX_NUM_BACKENDS];
static volatile sig_atomic_t reload_config_request = 0;
+static volatile sig_atomic_t restart_request = 0;
static void establish_persistent_connection(void);
static void discard_persistent_connection(void);
@@ -78,6 +79,10 @@ static void reload_config(void);
{ \
reload_config(); \
reload_config_request = 0; \
+ } else if (restart_request) \
+ { \
+ pool_log("worker process received restart request"); \
+ exit(1); \
} \
} while (0)
@@ -99,10 +104,13 @@ void do_worker_child(void)
signal(SIGHUP, reload_config_handler);
signal(SIGQUIT, my_signal_handler);
signal(SIGCHLD, SIG_IGN);
- signal(SIGUSR1, SIG_IGN);
+ signal(SIGUSR1, my_signal_handler);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
+ /* Initialize my backend status */
+ pool_initialize_private_backend_status();
+
/* Initialize per process context */
pool_init_process_context();
@@ -341,6 +349,13 @@ static RETSIGTYPE my_signal_handler(int sig)
case SIGINT:
case SIGQUIT:
exit(0);
+ break;
+
+ /* Failback or new node added */
+ case SIGUSR1:
+ restart_request = 1;
+ break;
+
default:
exit(1);
break;
[parent: e2af315e8394]