diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2014-05-31 07:38:15 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2014-05-31 07:42:46 +0200 |
commit | 38dfd6da00870e5a8f1e59258f351d295599720f (patch) | |
tree | 81da931a809d410ca9902c3207a5918359beb31f /src/poll.c | |
parent | 1d81d51e1e5e9db6c493ae2fe17280627fff15a6 (diff) | |
download | fastd-38dfd6da00870e5a8f1e59258f351d295599720f.tar fastd-38dfd6da00870e5a8f1e59258f351d295599720f.zip |
More signal handling fixes
Diffstat (limited to 'src/poll.c')
-rw-r--r-- | src/poll.c | 37 |
1 files changed, 20 insertions, 17 deletions
@@ -133,23 +133,19 @@ void fastd_poll_handle(void) { if (timeout < 0 || timeout > maintenance_timeout) timeout = maintenance_timeout; - sigset_t set, oldset; + sigset_t set; sigemptyset(&set); - pthread_sigmask(SIG_SETMASK, &set, &oldset); struct epoll_event events[16]; - int ret = epoll_wait(ctx.epoll_fd, events, 16, timeout); - if (ret < 0) { - if (errno == EINTR) - return; - + int ret = epoll_pwait(ctx.epoll_fd, events, 16, timeout, &set); + if (ret < 0 && errno != EINTR) exit_errno("epoll_wait"); - } - - pthread_sigmask(SIG_SETMASK, &oldset, NULL); fastd_update_time(); + if (ret < 0) + return; + size_t i; for (i = 0; i < (size_t)ret; i++) { if (events[i].data.ptr == &ctx.tunfd) { @@ -257,18 +253,25 @@ void fastd_poll_handle(void) { sigemptyset(&set); pthread_sigmask(SIG_SETMASK, &set, &oldset); - int ret = poll(VECTOR_DATA(ctx.pollfds), VECTOR_LEN(ctx.pollfds), timeout); - if (ret < 0) { - if (errno == EINTR) - return; - - exit_errno("poll"); + int ret = -1; + + if (!fastd_signalled()) { + /* + There is a race condition here: if a signal occurs after the fastd_signalled() check, but before the poll + call, poll() will be called with its normal timeout, potentially delaying the actual signal handling. On + OpenBSD we could use ppoll() to fix this, but on FreeBSD we're out of luck. + */ + ret = poll(VECTOR_DATA(ctx.pollfds), VECTOR_LEN(ctx.pollfds), timeout); + if (ret < 0 && errno != EINTR) + exit_errno("poll"); } pthread_sigmask(SIG_SETMASK, &oldset, NULL); - fastd_update_time(); + if (ret < 0) + return; + if (VECTOR_INDEX(ctx.pollfds, 0).revents & POLLIN) fastd_tuntap_handle(); if (VECTOR_INDEX(ctx.pollfds, 1).revents & POLLIN) |