diff options
author | Dan McGee <dan@archlinux.org> | 2008-10-12 21:07:49 -0500 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2008-10-12 21:35:30 -0500 |
commit | 30851a24ff68b00898565a1144926d83c623e6bf (patch) | |
tree | 59dc7db2a36f7f446db0869ad14b5cccc5144db6 | |
parent | f0e1846b51dfdeb095038b6b04d307ddfdec0029 (diff) |
Make interrupt handler async-safe
Calling printf() in a signal handler can be dangerous, so avoid it by
writing directly which is guaranteed to be safe according to signal(7).
Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r-- | src/pacman/pacman.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 3a56a9d3..0e133df6 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -36,6 +36,7 @@ #include <sys/utsname.h> /* uname */ #include <locale.h> /* setlocale */ #include <time.h> /* time_t */ +#include <errno.h> #if defined(PACMAN_DEBUG) && defined(HAVE_MCHECK_H) #include <mcheck.h> /* debug tracing (mtrace) */ #endif @@ -211,21 +212,34 @@ 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; + while((ret = write(fd, buf, count)) == -1 && errno == EINTR); + return(ret); +} + /** Catches thrown signals. Performs necessary cleanup to ensure database is * in a consistant state. * @param signum the thrown signal */ static RETSIGTYPE handler(int signum) { - if(signum==SIGSEGV) - { - /* write a log message and write to stderr */ - pm_printf(PM_LOG_ERROR, _("segmentation fault\n")); - pm_fprintf(stderr, PM_LOG_ERROR, - _("Internal pacman error: Segmentation fault.\n" - "Please submit a full bug report with --debug if appropriate.\n")); + int out = fileno(stdout); + int err = fileno(stderr); + if(signum == SIGSEGV) { + const char *msg1 = "error: segmentation fault\n"; + const char *msg2 = "Internal pacman error: Segmentation fault.\n" + "Please submit a full bug report with --debug if appropriate.\n"; + /* write a error message to out, the rest to err */ + xwrite(out, msg1, strlen(msg1)); + xwrite(err, msg2, strlen(msg2)); exit(signum); } else if((signum == SIGINT)) { + const char *msg = "\nInterrupt signal received\n"; + xwrite(err, msg, strlen(msg)); if(alpm_trans_interrupt() == 0) { /* a transaction is being interrupted, don't exit pacman yet. */ return; @@ -233,7 +247,7 @@ static RETSIGTYPE handler(int signum) /* no commiting transaction, we can release it now and then exit pacman */ alpm_trans_release(); /* output a newline to be sure we clear any line we may be on */ - printf("\n"); + xwrite(out, "\n", 1); } cleanup(signum); } |