[lvm-devel] [PATCH] signals: fix off-by-one when saving whether SIGINT was masked
Michael Chapman
mike at very.puzzling.org
Sun May 1 06:08:18 UTC 2016
sigint_allow saves whether SIGINT was masked in the _oldmasked array,
however an off-by-one in the calculation of the array index leads to the
wrong signal mask possibly being restored in sigint_restore.
This problem was discovered when the user attempted to use Ctrl+C to
abort a snapshot creation. The scenario can be recreated in GDB by
having it raise the signal immediately after the origin volume's
mappings have been suspended, e.g. when _lv_suspend_lv returns:
(gdb) handle SIGINT nostop noprint pass
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y
Signal Stop Print Pass to program Description
SIGINT No No Yes Interrupt
(gdb) b _lv_suspend_lv
Breakpoint 1 at 0x56bc0: file activate/activate.c, line 1273.
(gdb) r -s -L 20G -n y /dev/example/x
Starting program: /sbin/lvcreate -s -L 20G -n y /dev/example/x
Breakpoint 1, _lv_suspend_lv (...)
at activate/activate.c:1273
1273 {
(gdb) finish
Run till exit from #0 _lv_suspend_lv (...) at activate/activate.c:1273
Suspending example-x (253:20) with filesystem sync with device flush
Suspending example-x-real (253:21) with filesystem sync with device flush
1938 if (!_lv_suspend_lv(ondisk_lv, laopts, lockfs, flush_required)) {
Value returned is $1 = 1
(gdb) signal SIGINT
Continuing with signal SIGINT.
Program terminated with signal SIGINT, Interrupt.
The program no longer exists.
This leaves the mappings suspended:
# dmsetup info | grep -B1 SUSPENDED
Name: example-x
State: SUSPENDED
--
Name: example-x-real
State: SUSPENDED
With this fix the signal remains masked until the snapshot LV has been
fully created:
...
(gdb) finish
Run till exit from #0 _lv_suspend_lv (...) at activate/activate.c:1273
Suspending example-x (253:20) with filesystem sync with device flush
Suspending example-x-real (253:21) with filesystem sync with device flush
1938 if (!_lv_suspend_lv(ondisk_lv, laopts, lockfs, flush_required)) {
Value returned is $1 = 1
(gdb) signal SIGINT
Continuing with signal SIGINT.
Logical volume "y" created.
Program terminated with signal SIGINT, Interrupt.
The program no longer exists.
---
Please keep me CCed on any correspondence as I am not subscribed to this list.
lib/misc/lvm-signal.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/misc/lvm-signal.c b/lib/misc/lvm-signal.c
index 7e78407..30bdc01 100644
--- a/lib/misc/lvm-signal.c
+++ b/lib/misc/lvm-signal.c
@@ -85,7 +85,7 @@ void sigint_allow(void)
if (sigprocmask(0, NULL, &sigs))
log_sys_debug("sigprocmask", "");
- if ((_oldmasked[_handler_installed] = sigismember(&sigs, SIGINT))) {
+ if ((_oldmasked[_handler_installed - 1] = sigismember(&sigs, SIGINT))) {
sigdelset(&sigs, SIGINT);
if (sigprocmask(SIG_SETMASK, &sigs, NULL))
log_sys_debug("sigprocmask", "SIG_SETMASK");
--
2.5.5
More information about the lvm-devel
mailing list