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
This commit is contained in:
parent
d638e3029a
commit
514265b529
37
src/main.c
37
src/main.c
|
@ -232,13 +232,15 @@ static void i3_exit(void) {
|
||||||
* Unlinks the SHM log and re-raises the signal.
|
* 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);
|
fprintf(stderr, "Received signal %d, terminating\n", sig);
|
||||||
if (*shmlogname != '\0') {
|
if (*shmlogname != '\0') {
|
||||||
fprintf(stderr, "Closing SHM log \"%s\"\n", shmlogname);
|
fprintf(stderr, "Closing SHM log \"%s\"\n", shmlogname);
|
||||||
shm_unlink(shmlogname);
|
shm_unlink(shmlogname);
|
||||||
}
|
}
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
ev_signal_stop(loop, w);
|
||||||
raise(sig);
|
raise(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,31 +782,32 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
xcb_ungrab_server(conn);
|
xcb_ungrab_server(conn);
|
||||||
|
|
||||||
struct sigaction action;
|
|
||||||
|
|
||||||
action.sa_sigaction = handle_signal;
|
#define HANDLE_SIGNAL_EV(signum) \
|
||||||
action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
|
do { \
|
||||||
sigemptyset(&action.sa_mask);
|
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)
|
if (!disable_signalhandler)
|
||||||
setup_signal_handler();
|
setup_signal_handler();
|
||||||
else {
|
else {
|
||||||
/* Catch all signals with default action "Core", see signal(7) */
|
/* Catch all signals with default action "Core", see signal(7) */
|
||||||
if (sigaction(SIGQUIT, &action, NULL) == -1 ||
|
HANDLE_SIGNAL_EV(SIGQUIT);
|
||||||
sigaction(SIGILL, &action, NULL) == -1 ||
|
HANDLE_SIGNAL_EV(SIGILL);
|
||||||
sigaction(SIGABRT, &action, NULL) == -1 ||
|
HANDLE_SIGNAL_EV(SIGABRT);
|
||||||
sigaction(SIGFPE, &action, NULL) == -1 ||
|
HANDLE_SIGNAL_EV(SIGFPE);
|
||||||
sigaction(SIGSEGV, &action, NULL) == -1)
|
HANDLE_SIGNAL_EV(SIGSEGV);
|
||||||
ELOG("Could not setup signal handler");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Catch all signals with default action "Term", see signal(7) */
|
/* Catch all signals with default action "Term", see signal(7) */
|
||||||
if (sigaction(SIGHUP, &action, NULL) == -1 ||
|
HANDLE_SIGNAL_EV(SIGHUP);
|
||||||
sigaction(SIGINT, &action, NULL) == -1 ||
|
HANDLE_SIGNAL_EV(SIGINT);
|
||||||
sigaction(SIGALRM, &action, NULL) == -1 ||
|
HANDLE_SIGNAL_EV(SIGALRM);
|
||||||
sigaction(SIGUSR1, &action, NULL) == -1 ||
|
HANDLE_SIGNAL_EV(SIGTERM);
|
||||||
sigaction(SIGUSR2, &action, NULL) == -1)
|
HANDLE_SIGNAL_EV(SIGUSR1);
|
||||||
ELOG("Could not setup signal handler");
|
HANDLE_SIGNAL_EV(SIGUSR2);
|
||||||
|
|
||||||
/* Ignore SIGPIPE to survive errors when an IPC client disconnects
|
/* Ignore SIGPIPE to survive errors when an IPC client disconnects
|
||||||
* while we are sending him a message */
|
* while we are sending him a message */
|
||||||
|
|
Loading…
Reference in New Issue