diff options
author | Andrew Gregory <andrew.gregory.8@gmail.com> | 2015-11-30 12:36:30 -0500 |
---|---|---|
committer | Allan McRae <allan@archlinux.org> | 2015-12-05 18:09:39 +1000 |
commit | 4d2317dafb3c3aac56f9f604262d82fd1b396a19 (patch) | |
tree | fcc34638f1c0d75c523a237a8c58aec219b72c1a | |
parent | 220a3ce2b8177bb3cc8a7a20715b67d5cbf7fc71 (diff) | |
download | pacman-4d2317dafb3c3aac56f9f604262d82fd1b396a19.tar.xz |
move signal handlers to sighandler.[ch]
Signals are special because they run asynchronously, making them
non-trivial to handle correctly. Move the handlers a separate file to
offset them from the normal code and make them easier to separate into
individual functions without further cluttering pacman.c
Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
Signed-off-by: Allan McRae <allan@archlinux.org>
-rw-r--r-- | src/pacman/Makefile.am | 1 | ||||
-rw-r--r-- | src/pacman/pacman.c | 60 | ||||
-rw-r--r-- | src/pacman/sighandler.c | 92 | ||||
-rw-r--r-- | src/pacman/sighandler.h | 27 |
4 files changed, 122 insertions, 58 deletions
diff --git a/src/pacman/Makefile.am b/src/pacman/Makefile.am index b07c6706..14572cd4 100644 --- a/src/pacman/Makefile.am +++ b/src/pacman/Makefile.am @@ -40,6 +40,7 @@ pacman_SOURCES = \ pacman.h pacman.c \ query.c \ remove.c \ + sighandler.h sighandler.c \ sync.c \ callback.h callback.c \ upgrade.c \ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index ba86dec0..0f115c25 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -30,7 +30,6 @@ #include <limits.h> #include <getopt.h> #include <string.h> -#include <signal.h> #include <unistd.h> #include <sys/types.h> #include <sys/utsname.h> /* uname */ @@ -45,6 +44,7 @@ #include "pacman.h" #include "util.h" #include "conf.h" +#include "sighandler.h" /* list of targets specified on command line */ static alpm_list_t *pm_targets; @@ -294,51 +294,6 @@ static void cleanup(int ret) exit(ret); } -/** Write function that correctly handles EINTR. - */ -static ssize_t xwrite(int fd, const void *buf, size_t count) -{ - ssize_t ret; - do { - ret = write(fd, buf, count); - } while(ret == -1 && errno == EINTR); - return ret; -} - -/** Catches thrown signals. Performs necessary cleanup to ensure database is - * in a consistent state. - * @param signum the thrown signal - */ -static void handler(int signum) -{ - if(signum == SIGSEGV) { - const char msg[] = "\nerror: segmentation fault\n" - "Please submit a full bug report with --debug if appropriate.\n"; - xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1); - exit(signum); - } else if(signum == SIGINT || signum == SIGHUP) { - if(signum == SIGINT) { - const char msg[] = "\nInterrupt signal received\n"; - xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1); - } else { - const char msg[] = "\nHangup signal received\n"; - xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1); - } - if(alpm_trans_interrupt(config->handle) == 0) { - /* a transaction is being interrupted, don't exit pacman yet. */ - return; - } - } else if(signum == SIGWINCH) { - columns_cache_reset(); - return; - } - /* SIGINT/SIGHUP: no committing transaction, release it now and then exit pacman */ - alpm_unlock(config->handle); - /* output a newline to be sure we clear any line we may be on */ - xwrite(STDOUT_FILENO, "\n", 1); - _Exit(128 + signum); -} - static void invalid_opt(int used, const char *opt1, const char *opt2) { if(used) { @@ -1134,20 +1089,9 @@ int main(int argc, char *argv[]) { int ret = 0; size_t i; - struct sigaction new_action; - const int signals[] = { SIGHUP, SIGINT, SIGSEGV, SIGWINCH }; uid_t myuid = getuid(); - /* Set signal handlers */ - /* Set up the structure to specify the new action. */ - new_action.sa_handler = handler; - sigemptyset(&new_action.sa_mask); - new_action.sa_flags = SA_RESTART; - - /* assign our handler to any signals we care about */ - for(i = 0; i < ARRAYSIZE(signals); i++) { - sigaction(signals[i], &new_action, NULL); - } + install_signal_handlers(); /* i18n init */ #if defined(ENABLE_NLS) diff --git a/src/pacman/sighandler.c b/src/pacman/sighandler.c new file mode 100644 index 00000000..d488ecec --- /dev/null +++ b/src/pacman/sighandler.c @@ -0,0 +1,92 @@ +/* + * sighandler.c + * + * Copyright (c) 2015 Pacman Development Team <pacman-dev@archlinux.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <errno.h> +#include <signal.h> +#include <unistd.h> + +#include <alpm.h> + +#include "conf.h" +#include "sighandler.h" +#include "util.h" + +/** Write function that correctly handles EINTR. + */ +static ssize_t xwrite(int fd, const void *buf, size_t count) +{ + ssize_t ret; + do { + ret = write(fd, buf, count); + } while(ret == -1 && errno == EINTR); + return ret; +} + +/** Catches thrown signals. Performs necessary cleanup to ensure database is + * in a consistent state. + * @param signum the thrown signal + */ +static void handler(int signum) +{ + if(signum == SIGSEGV) { + const char msg[] = "\nerror: segmentation fault\n" + "Please submit a full bug report with --debug if appropriate.\n"; + xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1); + exit(signum); + } else if(signum == SIGINT || signum == SIGHUP) { + if(signum == SIGINT) { + const char msg[] = "\nInterrupt signal received\n"; + xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1); + } else { + const char msg[] = "\nHangup signal received\n"; + xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1); + } + if(alpm_trans_interrupt(config->handle) == 0) { + /* a transaction is being interrupted, don't exit pacman yet. */ + return; + } + } else if(signum == SIGWINCH) { + columns_cache_reset(); + return; + } + /* SIGINT/SIGHUP: no committing transaction, release it now and then exit pacman */ + alpm_unlock(config->handle); + /* output a newline to be sure we clear any line we may be on */ + xwrite(STDOUT_FILENO, "\n", 1); + _Exit(128 + signum); +} + +void install_signal_handlers(void) +{ + struct sigaction new_action; + const int signals[] = { SIGHUP, SIGINT, SIGSEGV, SIGWINCH }; + size_t i; + /* Set signal handlers */ + /* Set up the structure to specify the new action. */ + new_action.sa_handler = handler; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = SA_RESTART; + + /* assign our handler to any signals we care about */ + for(i = 0; i < ARRAYSIZE(signals); i++) { + sigaction(signals[i], &new_action, NULL); + } +} + +/* vim: set noet: */ diff --git a/src/pacman/sighandler.h b/src/pacman/sighandler.h new file mode 100644 index 00000000..f7abc9ee --- /dev/null +++ b/src/pacman/sighandler.h @@ -0,0 +1,27 @@ +/* + * sighandler.h + * + * Copyright (c) 2015 Pacman Development Team <pacman-dev@archlinux.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _PM_SIGHANDLER_H +#define _PM_SIGHANDLER_H + +void install_signal_handlers(void); + +#endif /* _PM_SIGHANDLER_H */ + +/* vim: set noet: */ |