From 2f9cce9150520a1a72ef02a71506c89bd442de4e Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Fri, 10 Nov 2017 22:18:40 +0100 Subject: [PATCH] Do NOT exit event loop on timer/signal watcher error This patch fixes a blocking issue discovered in the Finit project. At shutdown, or when there is any problem with a timer or signal watcher, the event loop is abruptly terminated. Instead of unconditionally exiting the event loop on problems with a single watcher, invalidate the watcher and run the callback one last time with UEV_ERROR in the events argument. This is a semantic change wrt. watchers and their callbacks, so the major version number will be bumped accordingly to signal the severity of this change. From now on it is STRONGLY recommended that each call back function check for UEV_ERROR. Signed-off-by: Joachim Nilsson --- src/private.h | 2 +- src/uev.c | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/private.h b/src/private.h index c8100e9..775b1e3 100644 --- a/src/private.h +++ b/src/private.h @@ -38,7 +38,7 @@ typedef enum { } uev_type_t; /* Event mask, used internally only. */ -#define UEV_EVENT_MASK (UEV_READ | UEV_WRITE | UEV_PRI | UEV_HUP | UEV_RDHUP | UEV_EDGE | UEV_ONESHOT) +#define UEV_EVENT_MASK (UEV_ERROR | UEV_READ | UEV_WRITE | UEV_PRI | UEV_HUP | UEV_RDHUP | UEV_EDGE | UEV_ONESHOT) /* Main libuEv context type */ typedef struct { diff --git a/src/uev.c b/src/uev.c index 1d788c5..d51ac57 100644 --- a/src/uev.c +++ b/src/uev.c @@ -74,6 +74,14 @@ static int has_data(int fd) return 0; } +/* Set error condition and remove watcher from set */ +static void invalidate_watcher(uev_t *w, struct epoll_event *event) +{ + event->events = UEV_ERROR; + w->active = 0; + LIST_REMOVE(w, link); +} + /* Private to libuEv, do not use directly! */ int _uev_watcher_init(uev_ctx_t *ctx, uev_t *w, uev_type_t type, uev_cb_t *cb, void *arg, int fd, int events) { @@ -359,12 +367,10 @@ int uev_run(uev_ctx_t *ctx, int flags) uint64_t exp; if (read(w->fd, &exp, sizeof(exp)) != sizeof(exp)) { - if (errno != ECANCELED) { - uev_exit(ctx); - return -3; - } - - events[i].events = UEV_HUP; + if (errno != ECANCELED) + invalidate_watcher(w, &events[i]); + else + events[i].events = UEV_HUP; } if (!w->u.c.interval) @@ -377,8 +383,7 @@ int uev_run(uev_ctx_t *ctx, int flags) uint64_t exp; if (read(w->fd, &exp, sizeof(exp)) != sizeof(exp)) { - uev_exit(ctx); - return -3; + invalidate_watcher(w, &events[i]); } if (!w->u.t.period) @@ -389,10 +394,8 @@ int uev_run(uev_ctx_t *ctx, int flags) struct signalfd_siginfo fdsi; ssize_t sz = sizeof(fdsi); - if (read(w->fd, &fdsi, sz) != sz) { - uev_exit(ctx); - return -4; - } + if (read(w->fd, &fdsi, sz) != sz) + invalidate_watcher(w, &events[i]); } if (w->cb)