From: Saverio Proto Date: Wed, 28 May 2014 19:49:23 +0000 (+0200) Subject: Revert "Remove support for UNIX signals in the event library." X-Git-Url: http://git.meshlink.io/?p=meshlink;a=commitdiff_plain;h=cb258d6fe7c84bd5f5896bd1a49a66b7197cb73b Revert "Remove support for UNIX signals in the event library." This reverts commit 12fd793a46d1695bedb96a5d9531dfd9f3efd7be. --- diff --git a/src/event.c b/src/event.c index cfc6d899..d23f43bb 100644 --- a/src/event.c +++ b/src/event.c @@ -1,5 +1,5 @@ /* - event.c -- I/O and timeout event handling + event.c -- I/O, timeout and signal event handling Copyright (C) 2014 Guus Sliepen This program is free software; you can redistribute it and/or modify @@ -117,6 +117,49 @@ void timeout_del(event_loop_t *loop, timeout_t *timeout) { timeout->tv = (struct timeval){0, 0}; } +static int signal_compare(const signal_t *a, const signal_t *b) { + return (int)a->signum - (int)b->signum; +} + +static void signalio_handler(event_loop_t *loop, void *data, int flags) { + unsigned char signum; + if(read(loop->pipefd[0], &signum, 1) != 1) + return; + + signal_t *sig = splay_search(&loop->signals, &((signal_t){.signum = signum})); + if(sig) + sig->cb(loop, sig->data); +} + +static void pipe_init(event_loop_t *loop) { + if(!pipe(loop->pipefd)) + io_add(loop, &loop->signalio, signalio_handler, NULL, loop->pipefd[0], IO_READ); +} + +void signal_add(event_loop_t *loop, signal_t *sig, signal_cb_t cb, void *data, uint8_t signum) { + if(sig->cb) + return; + + sig->cb = cb; + sig->data = data; + sig->signum = signum; + sig->node.data = sig; + + if(loop->pipefd[0] == -1) + pipe_init(loop); + + if(!splay_insert_node(&loop->signals, &sig->node)) + abort(); +} + +void signal_del(event_loop_t *loop, signal_t *sig) { + if(!sig->cb) + return; + + splay_unlink_node(&loop->signals, &sig->node); + sig->cb = NULL; +} + bool event_loop_run(event_loop_t *loop) { loop->running = true; @@ -187,6 +230,9 @@ void event_loop_stop(event_loop_t *loop) { void event_loop_init(event_loop_t *loop) { loop->ios.compare = (splay_compare_t)io_compare; loop->timeouts.compare = (splay_compare_t)timeout_compare; + loop->signals.compare = (splay_compare_t)signal_compare; + loop->pipefd[0] = -1; + loop->pipefd[1] = -1; gettimeofday(&loop->now, NULL); } @@ -195,4 +241,6 @@ void event_loop_exit(event_loop_t *loop) { splay_free_node(&loop->ios, node); for splay_each(timeout_t, timeout, &loop->timeouts) splay_free_node(&loop->timeouts, node); + for splay_each(signal_t, signal, &loop->signals) + splay_free_node(&loop->signals, node); } diff --git a/src/event.h b/src/event.h index 272243ff..e49732af 100644 --- a/src/event.h +++ b/src/event.h @@ -1,5 +1,5 @@ /* - event.h -- I/O and timeout event handling + event.h -- I/O, timeout and signal event handling Copyright (C) 2014 Guus Sliepen This program is free software; you can redistribute it and/or modify @@ -29,6 +29,7 @@ typedef struct event_loop_t event_loop_t; typedef void (*io_cb_t)(event_loop_t *loop, void *data, int flags); typedef void (*timeout_cb_t)(event_loop_t *loop, void *data); +typedef void (*signal_cb_t)(event_loop_t *loop, void *data); typedef struct io_t { int fd; @@ -45,6 +46,13 @@ typedef struct timeout_t { struct splay_node_t node; } timeout_t; +typedef struct signal_t { + int signum; + signal_cb_t cb; + void *data; + struct splay_node_t node; +} signal_t; + struct event_loop_t { fd_set readfds; fd_set writefds; @@ -54,6 +62,10 @@ struct event_loop_t { splay_tree_t ios; splay_tree_t timeouts; + splay_tree_t signals; + + io_t signalio; + int pipefd[2]; void *data; }; @@ -66,6 +78,10 @@ extern void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, extern void timeout_del(event_loop_t *loop, timeout_t *timeout); extern void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timeval *tv); +extern void signal_add(event_loop_t *loop, signal_t *sig, signal_cb_t cb, void *data, uint8_t signum); +extern void signal_trigger(event_loop_t *loop, signal_t *sig); +extern void signal_del(event_loop_t *loop, signal_t *sig); + extern void event_loop_init(event_loop_t *loop); extern void event_loop_exit(event_loop_t *loop); extern bool event_loop_run(event_loop_t *loop);