mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
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.
This commit is contained in:
parent
287565fd5d
commit
fe4f83171d
@ -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");
|
||||
|
||||
handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
|
||||
handler.sa_handler = _catch_sigint;
|
||||
|
||||
/* Override the signal handler: shall not fail. */
|
||||
if (sigaction(SIGINT, &handler, &_oldhandler[_handler_installed - 1]))
|
||||
log_sys_debug("sigaction", "SIGINT");
|
||||
|
||||
/* Unmask SIGINT. Remember to mask it again on restore. */
|
||||
/* Unmask signals. Remember to mask it again on restore. */
|
||||
if (sigprocmask(0, NULL, &sigs))
|
||||
log_sys_debug("sigprocmask", "");
|
||||
|
||||
if ((_oldmasked[_handler_installed - 1] = sigismember(&sigs, SIGINT))) {
|
||||
sigdelset(&sigs, SIGINT);
|
||||
if (sigprocmask(SIG_SETMASK, &sigs, NULL))
|
||||
log_sys_debug("sigprocmask", "SIG_SETMASK");
|
||||
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);
|
||||
|
||||
handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
|
||||
handler.sa_handler = _catch_sigint;
|
||||
|
||||
/* 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 ((_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");
|
||||
}
|
||||
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 (sigaction(SIGINT, &_oldhandler[_handler_installed], NULL))
|
||||
log_sys_debug("sigaction", "SIGINT restore");
|
||||
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)))
|
||||
|
Loading…
Reference in New Issue
Block a user