diff options
author | Vladislavs Sokurenko <vladislavs.sokurenko@zabbix.com> | 2019-07-04 17:35:36 +0300 |
---|---|---|
committer | Vladislavs Sokurenko <vladislavs.sokurenko@zabbix.com> | 2019-07-04 17:38:48 +0300 |
commit | 8a76a4b4b670795796f70b69d170fd36b03cf2d4 (patch) | |
tree | 9a1befa16f59f28124efe314f9471350d7c1fcf6 | |
parent | d5d82f4270dd6b54be8d8cf01830f020fc30367f (diff) |
...G...PS. [ZBX-9867] fixed Zabbix daemon termination
(cherry picked from commit 857b9bea1fdb2e5f20642b10aeb8c4d5827615bb)
-rw-r--r-- | include/threads.h | 2 | ||||
-rw-r--r-- | src/libs/zbxcrypto/tls.c | 15 | ||||
-rw-r--r-- | src/libs/zbxdbcache/dbcache.c | 14 | ||||
-rw-r--r-- | src/libs/zbxdbupgrade/dbupgrade.c | 3 | ||||
-rw-r--r-- | src/libs/zbxlog/log.c | 4 | ||||
-rw-r--r-- | src/libs/zbxnix/fatal.c | 1 | ||||
-rw-r--r-- | src/libs/zbxnix/sighandler.c | 22 | ||||
-rw-r--r-- | src/libs/zbxsys/threads.c | 3 | ||||
-rw-r--r-- | src/zabbix_server/dbsyncer/dbsyncer.c | 42 | ||||
-rw-r--r-- | src/zabbix_server/poller/checks_snmp.c | 1 |
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); |