From 104c47d1068bc96dd4dfac8301fd2c3328d52413 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Mon, 26 Oct 2015 19:32:41 +0100 Subject: [PATCH] Add a proper signal handling The most common signals are now intercepted with SA_RESTART to allow a clean interruption. --- TODO | 2 -- cmdline/snapraid.c | 55 +++++++++++++++++++++++++++++++++------------- configure.ac | 2 +- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/TODO b/TODO index 570c690b..3d9ea59b 100644 --- a/TODO +++ b/TODO @@ -43,8 +43,6 @@ The same for directories, when recreating the directory tree. * If a directory exists with the same name of a parity/content file be more explicative on the error message. See: https://sourceforge.net/projects/snapraid/forums/forum/1677233/topic/4861034 -* Support interrupted operations with EINTR. For remote filesystems it could be relevant. - * Allow to specify more than one disk directories to cover the case of multi partitions. Different partitions have duplicate inode. The only way to support this is to add also a kind of device_id, increasing the memory required. diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c index 5f88ec4a..d1ac4d7b 100644 --- a/cmdline/snapraid.c +++ b/cmdline/snapraid.c @@ -370,14 +370,33 @@ volatile int global_interrupt = 0; /* LCOV_EXCL_START */ void signal_handler(int signum) { - switch (signum) { - case SIGINT : - global_interrupt = 1; - break; - } + (void)signum; + + /* report the request of interruption */ + global_interrupt = 1; } /* LCOV_EXCL_STOP */ +void signal_init(void) +{ +#if HAVE_SIGACTION + struct sigaction sa; + + sa.sa_handler = signal_handler; + sigemptyset(&sa.sa_mask); + + /* use the SA_RESTART to automatically restart interrupted system calls */ + sa.sa_flags = SA_RESTART; + + sigaction(SIGHUP, &sa, 0); + sigaction(SIGTERM, &sa, 0); + sigaction(SIGINT, &sa, 0); + sigaction(SIGQUIT, &sa, 0); +#else + signal(SIGINT, signal_handler); +#endif +} + #define OPERATION_DIFF 0 #define OPERATION_SYNC 1 #define OPERATION_CHECK 2 @@ -1062,8 +1081,8 @@ int main(int argc, char* argv[]) memory(); - /* intercept Ctrl+C */ - signal(SIGINT, &signal_handler); + /* intercept signals while operating */ + signal_init(); /* save the new state before the sync */ /* this allow to recover the case of the changes in the array after an aborted sync. */ @@ -1124,15 +1143,15 @@ int main(int argc, char* argv[]) memory(); - /* intercept Ctrl+C */ - signal(SIGINT, &signal_handler); + /* intercept signals while operating */ + signal_init(); state_dry(&state, blockstart, blockcount); } else if (operation == OPERATION_REHASH) { state_read(&state); - /* intercept Ctrl+C */ - signal(SIGINT, &signal_handler); + /* intercept signals while operating */ + signal_init(); state_rehash(&state); @@ -1144,8 +1163,8 @@ int main(int argc, char* argv[]) memory(); - /* intercept Ctrl+C */ - signal(SIGINT, &signal_handler); + /* intercept signals while operating */ + signal_init(); ret = state_scrub(&state, percentage, olderthan); @@ -1162,6 +1181,9 @@ int main(int argc, char* argv[]) } else if (operation == OPERATION_REWRITE) { state_read(&state); + /* intercept signals while operating */ + signal_init(); + state_write(&state); memory(); @@ -1174,6 +1196,9 @@ int main(int argc, char* argv[]) state_nano(&state); + /* intercept signals while operating */ + signal_init(); + state_write(&state); memory(); @@ -1225,8 +1250,8 @@ int main(int argc, char* argv[]) memory(); - /* intercept Ctrl+C */ - signal(SIGINT, &signal_handler); + /* intercept signals while operating */ + signal_init(); if (operation == OPERATION_CHECK) { ret = state_check(&state, 0, blockstart, blockcount); diff --git a/configure.ac b/configure.ac index f83bb9be..698244f0 100644 --- a/configure.ac +++ b/configure.ac @@ -72,7 +72,7 @@ AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[ dnl Checks for library functions. AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul]) -AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf]) +AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf sigaction]) AC_CHECK_FUNCS([ftruncate fallocate fsync access posix_fallocate posix_fadvise]) AC_CHECK_FUNCS([pread pwrite getc_unlocked ferror_unlocked fnmatch]) AC_CHECK_FUNCS([futimes futimens futimesat localtime_r])