From 717a2c87f3e6b798a75b683aaa684e65f41a4960 Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Tue, 16 Apr 2019 15:48:44 +0900 Subject: [PATCH] Fix DROP DATABASE failure. When DROP DATABASE gets executed, SIGUSR1 is sent to the Pgpool-II child process being issuing the command. In its SIGUSR1 handler, MASTER macro is called while closing all idle connections. The MACRO checks whether we are in failover process surely we are. As a result, the process exits and DROP DATABASE command never been issued. Per bug 486. However the reason of segfault in the report is not clear. After commit: https://git.postgresql.org/gitweb/?p=pgpool2.git;a=commit;h=66b5aacfcc045ec1485921a5884b637fcfb6fd73 Things could be different. Let the user test the latest version in the git repo and see if the problem is solved... --- src/include/pool.h | 2 +- src/protocol/child.c | 12 +++++++++++- src/protocol/pool_proto_modules.c | 25 +++++++++++++++++++++---- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/include/pool.h b/src/include/pool.h index a0a122029..383b30d75 100644 --- a/src/include/pool.h +++ b/src/include/pool.h @@ -570,7 +570,7 @@ extern volatile sig_atomic_t *InRecovery; extern char remote_ps_data[]; /* used for set_ps_display */ extern volatile sig_atomic_t got_sighup; extern volatile sig_atomic_t exit_request; - +extern volatile sig_atomic_t ignore_sigusr1; #define QUERY_STRING_BUFFER_LEN 1024 extern char query_string_buffer[]; /* last query string sent to simpleQuery() */ diff --git a/src/protocol/child.c b/src/protocol/child.c index 2987aeb4e..9172358f2 100644 --- a/src/protocol/child.c +++ b/src/protocol/child.c @@ -91,11 +91,15 @@ static void child_will_go_down(int code, Datum arg); static int opt_sort(const void *a, const void *b); /* - * non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived + * Non 0 means SIGTERM (smart shutdown) or SIGINT (fast shutdown) has arrived */ volatile sig_atomic_t exit_request = 0; static volatile sig_atomic_t alarm_enabled = false; +/* + * Ignore SIGUSR1 if requested. Used when DROP DATABASE is requested. + */ +volatile sig_atomic_t ignore_sigusr1 = 0; static int idle; /* non 0 means this child is in idle state */ static int accepted = 0; @@ -1102,6 +1106,12 @@ static RETSIGTYPE close_idle_connection(int sig) ConnectionInfo *info; int save_errno = errno; + /* + * DROP DATABSE is ongoing. + */ + if (ignore_sigusr1) + return; + #ifdef NOT_USED ereport(DEBUG1, (errmsg("close connection request received"))); diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c index c7fa492f1..7cfd13f2e 100644 --- a/src/protocol/pool_proto_modules.c +++ b/src/protocol/pool_proto_modules.c @@ -503,21 +503,38 @@ SimpleQuery(POOL_CONNECTION * frontend, */ if (is_drop_database(node)) { - int stime = 5; /* XXX give arbitrary time to allow + struct timeval stime; + + stime.tv_usec = 0; + stime.tv_sec = 5; /* XXX give arbitrary time to allow * closing idle connections */ ereport(DEBUG1, (errmsg("Query: sending SIGUSR1 signal to parent"))); + + ignore_sigusr1 = 1; /* disable SIGUSR1 handler */ register_node_operation_request(CLOSE_IDLE_REQUEST, NULL, 0, 0); /* - * we need to loop over here since we will get USR1 signal while + * We need to loop over here since we might get some signals while * sleeping */ - while (stime > 0) + for (;;) { - stime = sleep(stime); + int sts; + + errno = 0; + sts = select(0, NULL, NULL, NULL, &stime); + if (stime.tv_usec == 0 && stime.tv_sec == 0) + break; + if (sts != 0 && errno != EINTR) + { + elog(DEBUG1, "select(2) returns error: %s", strerror(errno)); + break; + } } + + ignore_sigusr1 = 0; } /*--------------------------------------------------------------------------- -- 2.39.5