From 4d2317dafb3c3aac56f9f604262d82fd1b396a19 Mon Sep 17 00:00:00 2001 From: Andrew Gregory Date: Mon, 30 Nov 2015 12:36:30 -0500 Subject: 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 Signed-off-by: Allan McRae --- src/pacman/Makefile.am | 1 + src/pacman/pacman.c | 60 ++------------------------------ src/pacman/sighandler.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/sighandler.h | 27 +++++++++++++++ 4 files changed, 122 insertions(+), 58 deletions(-) create mode 100644 src/pacman/sighandler.c create mode 100644 src/pacman/sighandler.h (limited to 'src') 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 #include #include -#include #include #include #include /* 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 + * + * 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 . + */ + +#include +#include +#include + +#include + +#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 + * + * 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 . + */ + +#ifndef _PM_SIGHANDLER_H +#define _PM_SIGHANDLER_H + +void install_signal_handlers(void); + +#endif /* _PM_SIGHANDLER_H */ + +/* vim: set noet: */ -- cgit v1.2.3-24-g4f1b