Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislavs Sokurenko <vladislavs.sokurenko@zabbix.com>2019-07-04 17:35:36 +0300
committerVladislavs Sokurenko <vladislavs.sokurenko@zabbix.com>2019-07-04 17:38:48 +0300
commit8a76a4b4b670795796f70b69d170fd36b03cf2d4 (patch)
tree9a1befa16f59f28124efe314f9471350d7c1fcf6
parentd5d82f4270dd6b54be8d8cf01830f020fc30367f (diff)
...G...PS. [ZBX-9867] fixed Zabbix daemon termination
(cherry picked from commit 857b9bea1fdb2e5f20642b10aeb8c4d5827615bb)
-rw-r--r--include/threads.h2
-rw-r--r--src/libs/zbxcrypto/tls.c15
-rw-r--r--src/libs/zbxdbcache/dbcache.c14
-rw-r--r--src/libs/zbxdbupgrade/dbupgrade.c3
-rw-r--r--src/libs/zbxlog/log.c4
-rw-r--r--src/libs/zbxnix/fatal.c1
-rw-r--r--src/libs/zbxnix/sighandler.c22
-rw-r--r--src/libs/zbxsys/threads.c3
-rw-r--r--src/zabbix_server/dbsyncer/dbsyncer.c42
-rw-r--r--src/zabbix_server/poller/checks_snmp.c1
10 files changed, 67 insertions, 40 deletions
diff --git a/include/threads.h b/include/threads.h
index 5fa6c981c86..3d8fdd29a77 100644
--- a/include/threads.h
+++ b/include/threads.h
@@ -72,7 +72,7 @@
#define zbx_sleep(sec) sleep((sec))
- #define zbx_thread_kill(h) kill(h, SIGTERM)
+ #define zbx_thread_kill(h) kill(h, SIGUSR2)
#define zbx_thread_kill_fatal(h) kill(h, SIGQUIT)
#endif /* _WINDOWS */
diff --git a/src/libs/zbxcrypto/tls.c b/src/libs/zbxcrypto/tls.c
index f4c367ac96d..3565f728857 100644
--- a/src/libs/zbxcrypto/tls.c
+++ b/src/libs/zbxcrypto/tls.c
@@ -2710,12 +2710,13 @@ void zbx_tls_init_child(void)
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
#ifndef _WINDOWS
- /* Invalid TLS parameters will cause exit. Once one process exits the parent process will send SIGTERM to */
+ /* Invalid TLS parameters will cause exit. Once one process exits the parent process will send SIGQUIT to */
/* child processes which may be on their way to exit on their own - do not interrupt them, block signal */
- /* SIGTERM and unblock it when TLS parameters are good and libraries are initialized. */
+ /* SIGQUIT and unblock it when TLS parameters are good and libraries are initialized. */
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGUSR2);
sigprocmask(SIG_BLOCK, &mask, &orig_mask);
zbx_tls_library_init(); /* on Unix initialize crypto libraries in child processes */
@@ -2903,12 +2904,13 @@ void zbx_tls_init_child(void)
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
#ifndef _WINDOWS
- /* Invalid TLS parameters will cause exit. Once one process exits the parent process will send SIGTERM to */
+ /* Invalid TLS parameters will cause exit. Once one process exits the parent process will send SIGQUIT to */
/* child processes which may be on their way to exit on their own - do not interrupt them, block signal */
- /* SIGTERM and unblock it when TLS parameters are good and libraries are initialized. */
+ /* SIGQUIT and unblock it when TLS parameters are good and libraries are initialized. */
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGUSR2);
sigprocmask(SIG_BLOCK, &mask, &orig_mask);
zbx_tls_library_init(); /* on Unix initialize crypto libraries in child processes */
@@ -3190,12 +3192,13 @@ void zbx_tls_init_child(void)
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
#ifndef _WINDOWS
- /* Invalid TLS parameters will cause exit. Once one process exits the parent process will send SIGTERM to */
+ /* Invalid TLS parameters will cause exit. Once one process exits the parent process will send SIGQUIT to */
/* child processes which may be on their way to exit on their own - do not interrupt them, block signal */
- /* SIGTERM and unblock it when TLS parameters are good and libraries are initialized. */
+ /* SIGQUIT and unblock it when TLS parameters are good and libraries are initialized. */
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGUSR2);
sigprocmask(SIG_BLOCK, &mask, &orig_mask);
zbx_tls_library_init(); /* on Unix initialize crypto libraries in child processes */
diff --git a/src/libs/zbxdbcache/dbcache.c b/src/libs/zbxdbcache/dbcache.c
index fad0476318d..b2850db0c53 100644
--- a/src/libs/zbxdbcache/dbcache.c
+++ b/src/libs/zbxdbcache/dbcache.c
@@ -3154,29 +3154,15 @@ void zbx_log_sync_history_cache_progress(void)
******************************************************************************/
void zbx_sync_history_cache(int *values_num, int *triggers_num, int *more)
{
- sigset_t orig_mask, mask;
-
zabbix_log(LOG_LEVEL_DEBUG, "In %s() history_num:%d", __func__, cache->history_num);
*values_num = 0;
*triggers_num = 0;
- sigemptyset(&mask);
- sigaddset(&mask, SIGTERM);
- sigaddset(&mask, SIGINT);
-
- if (0 > sigprocmask(SIG_BLOCK, &mask, &orig_mask))
- zabbix_log(LOG_LEVEL_WARNING, "cannot set sigprocmask to block the user signal");
-
if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
sync_server_history(values_num, triggers_num, more);
else
sync_proxy_history(values_num, more);
-
- if (0 > sigprocmask(SIG_SETMASK, &orig_mask, NULL))
- zabbix_log(LOG_LEVEL_WARNING,"cannot restore sigprocmask");
-
- zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
}
/******************************************************************************
diff --git a/src/libs/zbxdbupgrade/dbupgrade.c b/src/libs/zbxdbupgrade/dbupgrade.c
index b9f95c3dff3..f1ca923e9ad 100644
--- a/src/libs/zbxdbupgrade/dbupgrade.c
+++ b/src/libs/zbxdbupgrade/dbupgrade.c
@@ -933,9 +933,10 @@ int DBcheck_version(void)
if (db_optional >= patches[i].version)
continue;
- /* block SIGTERM, SIGINT to prevent interruption of statements that cause an implicit commit */
+ /* block signals to prevent interruption of statements that cause an implicit commit */
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGUSR2);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
diff --git a/src/libs/zbxlog/log.c b/src/libs/zbxlog/log.c
index b010a3646c7..fba23636495 100644
--- a/src/libs/zbxlog/log.c
+++ b/src/libs/zbxlog/log.c
@@ -232,9 +232,11 @@ static void lock_log(void)
{
sigset_t mask;
+ /* block signals to prevent deadlock on log file mutex when signal handler attempts to lock log */
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
- sigaddset(&mask, SIGTERM); /* block SIGTERM, SIGINT to prevent deadlock on log file mutex */
+ sigaddset(&mask, SIGUSR2);
+ sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
diff --git a/src/libs/zbxnix/fatal.c b/src/libs/zbxnix/fatal.c
index e77fb7f5dc9..eb862b4a4c2 100644
--- a/src/libs/zbxnix/fatal.c
+++ b/src/libs/zbxnix/fatal.c
@@ -62,6 +62,7 @@ const char *get_signal_name(int sig)
case SIGTERM: return "SIGTERM";
case SIGPIPE: return "SIGPIPE";
case SIGUSR1: return "SIGUSR1";
+ case SIGUSR2: return "SIGUSR2";
default: return "unknown";
}
}
diff --git a/src/libs/zbxnix/sighandler.c b/src/libs/zbxnix/sighandler.c
index 26f1000310f..f666b122cb5 100644
--- a/src/libs/zbxnix/sighandler.c
+++ b/src/libs/zbxnix/sighandler.c
@@ -95,7 +95,7 @@ static void alarm_signal_handler(int sig, siginfo_t *siginfo, void *context)
* *
* Function: terminate_signal_handler *
* *
- * Purpose: handle terminate signals: SIGQUIT, SIGINT, SIGTERM *
+ * Purpose: handle terminate signals: SIGQUIT, SIGINT, SIGTERM, SIGUSR2 *
* *
******************************************************************************/
static void terminate_signal_handler(int sig, siginfo_t *siginfo, void *context)
@@ -104,24 +104,13 @@ static void terminate_signal_handler(int sig, siginfo_t *siginfo, void *context)
if (!SIG_PARENT_PROCESS)
{
- zabbix_log(sig_parent_pid == SIG_CHECKED_FIELD(siginfo, si_pid) || SIGINT == sig || SIGTERM == sig ?
- LOG_LEVEL_DEBUG : LOG_LEVEL_WARNING,
- "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,"
- "reason:%d]. Exiting ...",
- sig, get_signal_name(sig),
- SIG_CHECKED_FIELD(siginfo, si_pid),
- SIG_CHECKED_FIELD(siginfo, si_uid),
- SIG_CHECKED_FIELD(siginfo, si_code));
-
- /* ignore terminate signal in children - the parent */
- /* process will send terminate signals instead */
- if (sig_parent_pid != SIG_CHECKED_FIELD(siginfo, si_pid))
- return;
-
+ /* the parent process can either politely ask a child process to finish it's work and perform cleanup */
+ /* by sending SIGUSR2 or terminate child process immediately without cleanup by sending SIGQUIT */
if (SIGQUIT == sig)
exit_with_failure();
- sig_exiting = 1;
+ if (SIGUSR2 == sig)
+ sig_exiting = 1;
}
else
{
@@ -192,6 +181,7 @@ void zbx_set_common_signal_handlers(void)
sigaction(SIGINT, &phan, NULL);
sigaction(SIGQUIT, &phan, NULL);
sigaction(SIGTERM, &phan, NULL);
+ sigaction(SIGUSR2, &phan, NULL);
phan.sa_sigaction = fatal_signal_handler;
sigaction(SIGILL, &phan, NULL);
diff --git a/src/libs/zbxsys/threads.c b/src/libs/zbxsys/threads.c
index dfbed362936..a4b75633003 100644
--- a/src/libs/zbxsys/threads.c
+++ b/src/libs/zbxsys/threads.c
@@ -57,9 +57,10 @@ void zbx_child_fork(pid_t *pid)
{
sigset_t mask, orig_mask;
- /* block SIGTERM, SIGINT and SIGCHLD during fork to avoid deadlock (we've seen one in __unregister_atfork()) */
+ /* block signals during fork to avoid deadlock (we've seen one in __unregister_atfork()) */
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGUSR2);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGQUIT);
diff --git a/src/zabbix_server/dbsyncer/dbsyncer.c b/src/zabbix_server/dbsyncer/dbsyncer.c
index ffb3a7d70eb..031cf17e7ca 100644
--- a/src/zabbix_server/dbsyncer/dbsyncer.c
+++ b/src/zabbix_server/dbsyncer/dbsyncer.c
@@ -31,6 +31,41 @@
extern int CONFIG_HISTSYNCER_FREQUENCY;
extern unsigned char process_type, program_type;
extern int server_num, process_num;
+static sigset_t orig_mask;
+
+/******************************************************************************
+ * *
+ * Function: block_signals *
+ * *
+ * Purpose: block signals to avoid interruption *
+ * *
+ ******************************************************************************/
+static void block_signals(void)
+{
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGUSR1);
+ sigaddset(&mask, SIGUSR2);
+ sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGINT);
+
+ if (0 > sigprocmask(SIG_BLOCK, &mask, &orig_mask))
+ zabbix_log(LOG_LEVEL_WARNING, "cannot set sigprocmask to block the signal");
+}
+
+/******************************************************************************
+ * *
+ * Function: unblock_signals *
+ * *
+ * Purpose: unblock signals after blocking *
+ * *
+ ******************************************************************************/
+static void unblock_signals(void)
+{
+ if (0 > sigprocmask(SIG_SETMASK, &orig_mask, NULL))
+ zabbix_log(LOG_LEVEL_WARNING,"cannot restore sigprocmask");
+}
/******************************************************************************
* *
@@ -67,7 +102,10 @@ ZBX_THREAD_ENTRY(dbsyncer_thread, args)
zbx_strcpy_alloc(&stats, &stats_alloc, &stats_offset, "started");
+ /* database APIs might not handle signals correctly and hang, block signals to avoid hanging */
+ block_signals();
DBconnect(ZBX_DB_CONNECT_NORMAL);
+ unblock_signals();
if (SUCCEED == zbx_is_export_enabled())
{
@@ -90,7 +128,11 @@ ZBX_THREAD_ENTRY(dbsyncer_thread, args)
zbx_log_sync_history_cache_progress();
}
+ /* database APIs might not handle signals correctly and hang, block signals to avoid hanging */
+ block_signals();
zbx_sync_history_cache(&values_num, &triggers_num, &more);
+ unblock_signals();
+
total_values_num += values_num;
total_triggers_num += triggers_num;
total_sec += zbx_time() - sec;
diff --git a/src/zabbix_server/poller/checks_snmp.c b/src/zabbix_server/poller/checks_snmp.c
index b9b8b62133e..b31e262bb38 100644
--- a/src/zabbix_server/poller/checks_snmp.c
+++ b/src/zabbix_server/poller/checks_snmp.c
@@ -2123,6 +2123,7 @@ void zbx_init_snmp(void)
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGUSR2);
sigaddset(&mask, SIGQUIT);
sigprocmask(SIG_BLOCK, &mask, &orig_mask);