From 514265b529ac78b7778eeee2db3dddb6f3a1c24c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 21 Sep 2012 16:35:25 +0200 Subject: [PATCH] Use ev_signal to avoid async-unsafe functions (Thanks Markus) Functions such as fprintf() might be unsafe to use in a signal handler, see http://stackoverflow.com/questions/3941271/#answer-3941563 By using ev_signal, libev will use a tiny signal handler which just passes on the information and then calls (outside of the signal handler) our callback function which can use fprintf() and other unsafe functions. fixes #803 --- src/main.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/main.c b/src/main.c index 8bae9957..a4bd1b9b 100644 --- a/src/main.c +++ b/src/main.c @@ -232,13 +232,15 @@ static void i3_exit(void) { * Unlinks the SHM log and re-raises the signal. * */ -static void handle_signal(int sig, siginfo_t *info, void *data) { +static void handle_signal(struct ev_loop *loop, ev_signal *w, int revents) { + int sig = w->signum; fprintf(stderr, "Received signal %d, terminating\n", sig); if (*shmlogname != '\0') { fprintf(stderr, "Closing SHM log \"%s\"\n", shmlogname); shm_unlink(shmlogname); } fflush(stderr); + ev_signal_stop(loop, w); raise(sig); } @@ -780,31 +782,32 @@ int main(int argc, char *argv[]) { } xcb_ungrab_server(conn); - struct sigaction action; - action.sa_sigaction = handle_signal; - action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; - sigemptyset(&action.sa_mask); +#define HANDLE_SIGNAL_EV(signum) \ + do { \ + struct ev_signal *signal_watcher = scalloc(sizeof(struct ev_signal)); \ + ev_signal_init(signal_watcher, handle_signal, signum); \ + ev_signal_start(main_loop, signal_watcher); \ + } while (0) if (!disable_signalhandler) setup_signal_handler(); else { /* Catch all signals with default action "Core", see signal(7) */ - if (sigaction(SIGQUIT, &action, NULL) == -1 || - sigaction(SIGILL, &action, NULL) == -1 || - sigaction(SIGABRT, &action, NULL) == -1 || - sigaction(SIGFPE, &action, NULL) == -1 || - sigaction(SIGSEGV, &action, NULL) == -1) - ELOG("Could not setup signal handler"); + HANDLE_SIGNAL_EV(SIGQUIT); + HANDLE_SIGNAL_EV(SIGILL); + HANDLE_SIGNAL_EV(SIGABRT); + HANDLE_SIGNAL_EV(SIGFPE); + HANDLE_SIGNAL_EV(SIGSEGV); } /* Catch all signals with default action "Term", see signal(7) */ - if (sigaction(SIGHUP, &action, NULL) == -1 || - sigaction(SIGINT, &action, NULL) == -1 || - sigaction(SIGALRM, &action, NULL) == -1 || - sigaction(SIGUSR1, &action, NULL) == -1 || - sigaction(SIGUSR2, &action, NULL) == -1) - ELOG("Could not setup signal handler"); + HANDLE_SIGNAL_EV(SIGHUP); + HANDLE_SIGNAL_EV(SIGINT); + HANDLE_SIGNAL_EV(SIGALRM); + HANDLE_SIGNAL_EV(SIGTERM); + HANDLE_SIGNAL_EV(SIGUSR1); + HANDLE_SIGNAL_EV(SIGUSR2); /* Ignore SIGPIPE to survive errors when an IPC client disconnects * while we are sending him a message */ -- 2.39.5