X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fevent.c;h=b6def622023e0ade5f513af787225f1fba0c37f2;hb=87b60ec7e32d14ce0ebe20bb19a342d9e0aac70a;hp=85ea9bb8c776b4cf319534b2761adcc23add84e2;hpb=a20765791b2a40ddd58452e8f74b0737f1f1f28e;p=meshlink diff --git a/src/event.c b/src/event.c index 85ea9bb8..b6def622 100644 --- a/src/event.c +++ b/src/event.c @@ -26,8 +26,6 @@ #include "utils.h" #include "xalloc.h" -event_loop_t *loop; - static int io_compare(const io_t *a, const io_t *b) { return a->fd - b->fd; } @@ -83,6 +81,8 @@ void io_del(event_loop_t *loop, io_t *io) { if(!io->cb) return; + loop->deletion = true; + io_set(loop, io, 0); splay_unlink_node(&loop->ios, &io->node); @@ -90,6 +90,9 @@ void io_del(event_loop_t *loop, io_t *io) { } void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv) { + if(!timeout->cb) + timeout->tv = (struct timeval){0, 0}; + timeout->cb = cb; timeout->data = data; timeout->node.data = timeout; @@ -114,6 +117,8 @@ void timeout_del(event_loop_t *loop, timeout_t *timeout) { if(!timeout->cb) return; + loop->deletion = true; + splay_unlink_node(&loop->timeouts, &timeout->node); timeout->cb = 0; timeout->tv = (struct timeval){0, 0}; @@ -138,6 +143,14 @@ static void pipe_init(event_loop_t *loop) { io_add(loop, &loop->signalio, signalio_handler, NULL, loop->pipefd[0], IO_READ); } +void signal_trigger(event_loop_t *loop, signal_t *sig) { + + uint8_t signum = sig->signum; + write(loop->pipefd[1], &signum, 1); + return; + +} + void signal_add(event_loop_t *loop, signal_t *sig, signal_cb_t cb, void *data, uint8_t signum) { if(sig->cb) return; @@ -158,6 +171,8 @@ void signal_del(event_loop_t *loop, signal_t *sig) { if(!sig->cb) return; + loop->deletion = true; + splay_unlink_node(&loop->signals, &sig->node); sig->cb = NULL; } @@ -208,11 +223,21 @@ bool event_loop_run(event_loop_t *loop) { if(!n) continue; + // Normally, splay_each allows the current node to be deleted. However, + // it can be that one io callback triggers the deletion of another io, + // so we have to detect this and break the loop. + + loop->deletion = false; + for splay_each(io_t, io, &loop->ios) { - if(FD_ISSET(io->fd, &writable)) + if(FD_ISSET(io->fd, &writable) && io->cb) io->cb(loop, io->data, IO_WRITE); - else if(FD_ISSET(io->fd, &readable)) + if(loop->deletion) + break; + if(FD_ISSET(io->fd, &readable) && io->cb) io->cb(loop, io->data, IO_READ); + if(loop->deletion) + break; } } @@ -240,9 +265,9 @@ void event_loop_init(event_loop_t *loop) { void event_loop_exit(event_loop_t *loop) { for splay_each(io_t, io, &loop->ios) - splay_free_node(&loop->ios, node); + splay_unlink_node(&loop->ios, node); for splay_each(timeout_t, timeout, &loop->timeouts) - splay_free_node(&loop->timeouts, node); + splay_unlink_node(&loop->timeouts, node); for splay_each(signal_t, signal, &loop->signals) - splay_free_node(&loop->signals, node); + splay_unlink_node(&loop->signals, node); }