summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2021-04-01 11:32:29 +0200
committerZdenek Kabelac <zkabelac@redhat.com>2021-04-06 21:26:57 +0200
commitfe4f83171d43ed764b2342f2081db8d9e8ce9343 (patch)
tree52dae6dbc536a1728619f509a04a28c34524f0f7
parent287565fd5dd5f49f1a51c6cd9ebdc9c20ebc7730 (diff)
downloadlvm2-fe4f83171d43ed764b2342f2081db8d9e8ce9343.tar.gz
signals: support also SIGTERM for breaking command
If we are signaled with SIGTERM it should be at least as good as with SIGINT - as the command should stop ASAP. So when lvm2 command allows signal handling we also enable SIGTERM handling. If there are some other signals we should handle equally - we could just extend array.
-rw-r--r--lib/misc/lvm-signal.c76
1 files changed, 49 insertions, 27 deletions
diff --git a/lib/misc/lvm-signal.c b/lib/misc/lvm-signal.c
index b1653a85c..67012af86 100644
--- a/lib/misc/lvm-signal.c
+++ b/lib/misc/lvm-signal.c
@@ -26,8 +26,19 @@ static volatile sig_atomic_t _handler_installed = 0;
/* Support 3 level nesting, increase if needed more */
#define MAX_SIGINTS 3
-static struct sigaction _oldhandler[MAX_SIGINTS];
-static int _oldmasked[MAX_SIGINTS];
+
+struct ar_sigs {
+ int sig;
+ const char *name;
+ int oldmasked[MAX_SIGINTS];
+ struct sigaction oldhandler[MAX_SIGINTS];
+};
+
+/* List of signals we want to allow/restore */
+static struct ar_sigs _ar_sigs[] = {
+ { SIGINT, "SIGINT" },
+ { SIGTERM, "SIGTERM" },
+};
static void _catch_sigint(int unused __attribute__((unused)))
{
@@ -58,6 +69,7 @@ void sigint_clear(void)
void sigint_allow(void)
{
+ int i, mask = 0;
struct sigaction handler;
sigset_t sigs;
@@ -70,30 +82,37 @@ void sigint_allow(void)
if (++_handler_installed > MAX_SIGINTS)
return;
- /* Grab old sigaction for SIGINT: shall not fail. */
- if (sigaction(SIGINT, NULL, &handler))
- log_sys_debug("sigaction", "SIGINT");
+ /* Unmask signals. Remember to mask it again on restore. */
+ if (sigprocmask(0, NULL, &sigs))
+ log_sys_debug("sigprocmask", "");
- handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
- handler.sa_handler = _catch_sigint;
+ for (i = 0; i < DM_ARRAY_SIZE(_ar_sigs); ++i) {
+ /* Grab old sigaction for SIGNAL: shall not fail. */
+ if (sigaction(_ar_sigs[i].sig, NULL, &handler))
+ log_sys_debug("sigaction", _ar_sigs[i].name);
- /* Override the signal handler: shall not fail. */
- if (sigaction(SIGINT, &handler, &_oldhandler[_handler_installed - 1]))
- log_sys_debug("sigaction", "SIGINT");
+ handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
+ handler.sa_handler = _catch_sigint;
- /* Unmask SIGINT. Remember to mask it again on restore. */
- if (sigprocmask(0, NULL, &sigs))
- log_sys_debug("sigprocmask", "");
+ /* Override the signal handler: shall not fail. */
+ if (sigaction(_ar_sigs[i].sig, &handler, &_ar_sigs[i].oldhandler[_handler_installed - 1]))
+ log_sys_debug("sigaction", _ar_sigs[i].name);
- if ((_oldmasked[_handler_installed - 1] = sigismember(&sigs, SIGINT))) {
- sigdelset(&sigs, SIGINT);
- if (sigprocmask(SIG_SETMASK, &sigs, NULL))
- log_sys_debug("sigprocmask", "SIG_SETMASK");
+ if ((_ar_sigs[i].oldmasked[_handler_installed - 1] = sigismember(&sigs, _ar_sigs[i].sig))) {
+ sigdelset(&sigs, _ar_sigs[i].sig);
+ mask = 1;
+ }
}
+
+ if (mask && sigprocmask(SIG_SETMASK, &sigs, NULL))
+ log_sys_debug("sigprocmask", "SIG_SETMASK");
}
void sigint_restore(void)
{
+ int i, mask = 0;
+ sigset_t sigs;
+
if (memlock_count_daemon())
return;
@@ -102,16 +121,19 @@ void sigint_restore(void)
return;
/* Nesting count went below MAX_SIGINTS. */
- if (_oldmasked[_handler_installed]) {
- sigset_t sigs;
- sigprocmask(0, NULL, &sigs);
- sigaddset(&sigs, SIGINT);
- if (sigprocmask(SIG_SETMASK, &sigs, NULL))
- log_sys_debug("sigprocmask", "SIG_SETMASK");
- }
-
- if (sigaction(SIGINT, &_oldhandler[_handler_installed], NULL))
- log_sys_debug("sigaction", "SIGINT restore");
+ sigprocmask(0, NULL, &sigs);
+ for (i = 0; i < DM_ARRAY_SIZE(_ar_sigs); ++i)
+ if (_ar_sigs[i].oldmasked[_handler_installed]) {
+ sigaddset(&sigs, _ar_sigs[i].sig);
+ mask = 1;
+ }
+
+ if (mask && sigprocmask(SIG_SETMASK, &sigs, NULL))
+ log_sys_debug("sigprocmask", "SIG_SETMASK");
+
+ for (i = 0; i < DM_ARRAY_SIZE(_ar_sigs); ++i)
+ if (sigaction(_ar_sigs[i].sig, &_ar_sigs[i].oldhandler[_handler_installed], NULL))
+ log_sys_debug("sigaction", _ar_sigs[i].name);
}
void block_signals(uint32_t flags __attribute__((unused)))