2
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3
* Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
5
* This file is part of LVM2.
7
* This copyrighted material is made available to anyone wishing to use,
8
* modify, copy, or redistribute it subject to the terms and conditions
9
* of the GNU Lesser General Public License v.2.1.
11
* You should have received a copy of the GNU Lesser General Public License
12
* along with this program; if not, write to the Free Software Foundation,
13
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
#include "lvm-signal.h"
21
static sigset_t _oldset;
22
static int _signals_blocked = 0;
23
static volatile sig_atomic_t _sigint_caught = 0;
24
static volatile sig_atomic_t _handler_installed;
26
/* Support 3 level nesting, increase if needed more */
28
static struct sigaction _oldhandler[MAX_SIGINTS];
29
static int _oldmasked[MAX_SIGINTS];
31
static void _catch_sigint(int unused __attribute__((unused)))
36
int sigint_caught(void) {
38
log_error("Interrupted...");
40
return _sigint_caught;
43
void sigint_clear(void)
49
* Temporarily allow keyboard interrupts to be intercepted and noted;
50
* saves interrupt handler state for sigint_restore(). Users should
51
* use the sigint_caught() predicate to check whether interrupt was
52
* requested and act appropriately. Interrupt flags are never
53
* cleared automatically by this code, but the tools clear the flag
54
* before running each command in lvm_run_command(). All other places
55
* where the flag needs to be cleared need to call sigint_clear().
58
void sigint_allow(void)
60
struct sigaction handler;
64
* Do not overwrite the backed-up handler data -
65
* just increase nesting count.
67
if (++_handler_installed >= MAX_SIGINTS)
70
/* Grab old sigaction for SIGINT: shall not fail. */
71
if (sigaction(SIGINT, NULL, &handler))
72
log_sys_debug("sigaction", "SIGINT");
74
handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
75
handler.sa_handler = _catch_sigint;
77
/* Override the signal handler: shall not fail. */
78
if (sigaction(SIGINT, &handler, &_oldhandler[_handler_installed - 1]))
79
log_sys_debug("sigaction", "SIGINT");
81
/* Unmask SIGINT. Remember to mask it again on restore. */
82
if (sigprocmask(0, NULL, &sigs))
83
log_sys_debug("sigprocmask", "");
85
if ((_oldmasked[_handler_installed] = sigismember(&sigs, SIGINT))) {
86
sigdelset(&sigs, SIGINT);
87
if (sigprocmask(SIG_SETMASK, &sigs, NULL))
88
log_sys_debug("sigprocmask", "SIG_SETMASK");
92
void sigint_restore(void)
94
if (!_handler_installed ||
95
--_handler_installed >= MAX_SIGINTS)
98
/* Nesting count went bellow MAX_SIGINTS. */
99
if (_oldmasked[_handler_installed]) {
101
sigprocmask(0, NULL, &sigs);
102
sigaddset(&sigs, SIGINT);
103
if (sigprocmask(SIG_SETMASK, &sigs, NULL))
104
log_sys_debug("sigprocmask", "SIG_SETMASK");
107
if (sigaction(SIGINT, &_oldhandler[_handler_installed], NULL))
108
log_sys_debug("sigaction", "SIGINT restore");
111
void block_signals(uint32_t flags __attribute__((unused)))
115
if (_signals_blocked)
118
if (sigfillset(&set)) {
119
log_sys_error("sigfillset", "_block_signals");
123
if (sigprocmask(SIG_SETMASK, &set, &_oldset)) {
124
log_sys_error("sigprocmask", "_block_signals");
128
_signals_blocked = 1;
131
void unblock_signals(void)
133
/* Don't unblock signals while any locks are held */
134
if (!_signals_blocked)
137
if (sigprocmask(SIG_SETMASK, &_oldset, NULL)) {
138
log_sys_error("sigprocmask", "_block_signals");
142
_signals_blocked = 0;