pgpool2.git / summary / log / commit / refs
commit f2d5a3b815cece78eeef0163d262656b4562d443
Author: Tatsuo Ishii <ishii@sraoss.co.jp>
Date: Thu Apr 14 11:01:56 2022 +0000
Fix exit_handler in pgpool main process.
It was allowed to be interrupted by signals (SIGTERM, SIGINT and
SOGQUIT) while the exit_handler. As a resit, exit_handler is executed
while executing exit_handler. This could cause infinite wait in
terminate_childrens() which is called from exit_handler. To prevent
this, protect variable "exiting" using semaphore to make sure that
only one instance of exit_handler runs at the same time.
Discussion: https://www.pgpool.net/pipermail/pgpool-hackers/2022-April/004149.html
src/include/pool.h | 3 ++-
src/main/pgpool_main.c | 44 +++++++++++++++++++++++++++++++++++++++-----
2 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/src/include/pool.h b/src/include/pool.h
index 1a892fc61..c8d97abfd 100644
--- a/src/include/pool.h
+++ b/src/include/pool.h
@@ -379,7 +379,7 @@ typedef enum
#define Min(x, y) ((x) < (y) ? (x) : (y))
-#define MAX_NUM_SEMAPHORES 8
+#define MAX_NUM_SEMAPHORES 9
#define CONN_COUNTER_SEM 0
#define REQUEST_INFO_SEM 1
#define SHM_CACHE_SEM 2
@@ -388,6 +388,7 @@ typedef enum
#define ACCEPT_FD_SEM 5
#define SI_CRITICAL_REGION_SEM 6
#define FOLLOW_PRIMARY_SEM 7
+#define MAIN_EXIT_HANDLER_SEM 8 /* used in exit_hander in pgpool main process */
#define MAX_REQUEST_QUEUE_SIZE 10
#define MAX_SEC_WAIT_FOR_CLUSTER_TRANSACTION 10 /* time in seconds to keep
diff --git a/src/main/pgpool_main.c b/src/main/pgpool_main.c
index 861d9a27d..f0d362ac1 100644
--- a/src/main/pgpool_main.c
+++ b/src/main/pgpool_main.c
@@ -229,8 +229,8 @@ extern char *pcp_conf_file; /* path for pcp.conf */
extern char *conf_file;
extern char *hba_file;
-static int exiting = 0; /* non 0 if I'm exiting */
-static int switching = 0; /* non 0 if I'm failing over or degenerating */
+static volatile sig_atomic_t exiting = 0; /* non 0 if I'm exiting */
+static volatile sig_atomic_t switching = 0; /* non 0 if I'm failing over or degenerating */
POOL_REQUEST_INFO *Req_info; /* request info area in shared memory */
volatile sig_atomic_t *InRecovery; /* non 0 if recovery is started */
@@ -1098,6 +1098,9 @@ terminate_all_childrens(int sig)
}
+/*
+ * Pgpool main process exit handler
+ */
static RETSIGTYPE exit_handler(int sig)
{
int *walk;
@@ -1121,11 +1124,42 @@ static RETSIGTYPE exit_handler(int sig)
errno = save_errno;
return;
}
- exiting = 1;
- processState = EXITING;
+ /*
+ * Check if another exit handler instance is already running. It is
+ * possible that exit_handler is interrupted in the middle by other
+ * signal.
+ */
+ if (exiting)
+ {
+ ereport(LOG,
+ (errmsg("exit handler (signal: %d) called. but exit handler is already in progress", sig)));
+ POOL_SETMASK(&UnBlockSig);
+ errno = save_errno;
+ return;
+ }
+
+ /* Check to make sure that other exit handler is not running */
+ pool_semaphore_lock(MAIN_EXIT_HANDLER_SEM);
+ if (exiting == 0)
+ {
+ exiting = 1;
+ pool_semaphore_unlock(MAIN_EXIT_HANDLER_SEM);
+ }
+ else
+ {
+ pool_semaphore_unlock(MAIN_EXIT_HANDLER_SEM);
+ ereport(LOG,
+ (errmsg("exit handler (signal: %d) called. but exit handler is already in progress", sig)));
+ POOL_SETMASK(&UnBlockSig);
+ errno = save_errno;
+ return;
+ }
+
+ processState = EXITING;
ereport(LOG,
- (errmsg("shutting down")));
+ (errmsg("shutting down by signal %d", sig)));
+
/* Close listen socket if they are already initialized */
if (fds)
{
[parent: c13231cd2a08]