Skip to content

Commit 04ba252

Browse files
committed
eloop: Replace the inner eloop concept with waitfd
This is what we really want and saves the massive headache of managing two loops.
1 parent 95dbc8c commit 04ba252

File tree

2 files changed

+39
-40
lines changed

2 files changed

+39
-40
lines changed

src/eloop.c

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,18 @@
4949
#include <sys/epoll.h>
5050

5151
#include <linux/version.h>
52-
#include <poll.h>
5352
#define USE_EPOLL
5453
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
5554
#define HAVE_EPOLL_PWAIT2
5655
#endif
5756
#else
58-
#include <poll.h>
5957
#define USE_PPOLL
6058
#endif
6159

6260
#include <errno.h>
6361
#include <fcntl.h>
6462
#include <limits.h>
63+
#include <poll.h>
6564
#include <signal.h>
6665
#include <stdbool.h>
6766
#include <stdint.h>
@@ -154,8 +153,6 @@ struct eloop {
154153
#endif
155154
};
156155

157-
TAILQ_HEAD(eloop_head, eloop) eloops = TAILQ_HEAD_INITIALIZER(eloops);
158-
159156
#ifdef HAVE_REALLOCARRAY
160157
#define eloop_realloca reallocarray
161158
#else
@@ -832,7 +829,6 @@ eloop_new(void)
832829
}
833830
#endif
834831

835-
TAILQ_INSERT_TAIL(&eloops, eloop, next);
836832
return eloop;
837833
}
838834

@@ -848,15 +844,41 @@ eloop_free(struct eloop *eloop)
848844
close(eloop->fd);
849845
#endif
850846
free(eloop->fds);
851-
TAILQ_REMOVE(&eloops, eloop, next);
852847
free(eloop);
853848
}
854849

855-
#if defined(USE_KQUEUE)
850+
static unsigned short
851+
eloop_pollevents(struct pollfd *pfd)
852+
{
853+
unsigned short events = 0;
854+
855+
if (pfd->revents & POLLIN)
856+
events |= ELE_READ;
857+
if (pfd->revents & POLLOUT)
858+
events |= ELE_WRITE;
859+
if (pfd->revents & POLLHUP)
860+
events |= ELE_HANGUP;
861+
if (pfd->revents & POLLERR)
862+
events |= ELE_ERROR;
863+
if (pfd->revents & POLLNVAL)
864+
events |= ELE_NVAL;
865+
return events;
866+
}
867+
868+
int
869+
eloop_waitfd(int fd)
870+
{
871+
struct pollfd pfd = { .fd = fd, .events = POLLIN };
872+
int err;
856873

857-
static int eloop_kqueue_signals[] = { SIGINT, SIGTERM };
858-
#define eloop_kqueue_nsignals \
859-
sizeof(eloop_kqueue_signals) / sizeof(eloop_kqueue_signals[0])
874+
err = ppoll(&pfd, 1, NULL, NULL);
875+
if (err == -1 || err == 0)
876+
return err;
877+
878+
return (int)eloop_pollevents(&pfd);
879+
}
880+
881+
#if defined(USE_KQUEUE)
860882

861883
static int
862884
eloop_run_kqueue(struct eloop *eloop, const struct timespec *ts)
@@ -866,32 +888,17 @@ eloop_run_kqueue(struct eloop *eloop, const struct timespec *ts)
866888
struct eloop_event *e;
867889
unsigned short events;
868890

869-
/* Inner loops generally don't have signals attached
870-
* but we do need to exit the loop to when interrupted
871-
* with SIGTERM or SIGINT. */
872-
if (eloop->nsignals == 0 && TAILQ_FIRST(&eloops)->nsignals) {
873-
eloop_signal_kqueue(eloop, eloop_kqueue_signals,
874-
eloop_kqueue_nsignals);
875-
eloop->signals = eloop_kqueue_signals;
876-
eloop->nsignals = eloop_kqueue_nsignals;
877-
}
878-
879891
n = kevent(eloop->fd, NULL, 0, eloop->fds, (KEVENT_N)eloop->nfds, ts);
880892
if (n == -1)
881893
return -1;
882894

883895
for (nn = n, ke = eloop->fds; nn != 0; nn--, ke++) {
884896
if (eloop->exitnow || eloop->events_invalid)
885897
break;
886-
e = (struct eloop_event *)ke->udata;
887898
if (ke->filter == EVFILT_SIGNAL) {
888-
if (eloop->signal_cb == NULL) {
889-
eloop_exit(eloop,
890-
ke->ident == SIGTERM ? EXIT_SUCCESS :
891-
EXIT_FAILURE);
892-
return nn;
893-
}
894-
eloop->signal_cb((int)ke->ident, eloop->signal_cb_ctx);
899+
if (eloop->signal_cb != NULL)
900+
eloop->signal_cb((int)ke->ident,
901+
eloop->signal_cb_ctx);
895902
continue;
896903
}
897904
if (ke->filter == EVFILT_READ)
@@ -911,6 +918,7 @@ eloop_run_kqueue(struct eloop *eloop, const struct timespec *ts)
911918
events |= ELE_HANGUP;
912919
if (ke->flags & EV_ERROR)
913920
events |= ELE_ERROR;
921+
e = (struct eloop_event *)ke->udata;
914922
e->cb(e->cb_arg, events);
915923
}
916924

@@ -1056,20 +1064,10 @@ eloop_start(struct eloop *eloop)
10561064

10571065
#ifndef USE_KQUEUE
10581066
if (eloop_nsig != 0) {
1059-
/* Inner loops generally don't have signals attached
1060-
* but we do need to exit the loop to when interrupted
1061-
* with SIGTERM or SIGINT. */
1062-
if (eloop->signal_cb == NULL) {
1063-
eloop_exit(eloop,
1064-
eloop_sig[eloop_nsig - 1] == SIGTERM ?
1065-
EXIT_SUCCESS :
1066-
EXIT_FAILURE);
1067-
return 0;
1068-
}
1069-
int n = eloop_sig[--eloop_nsig];
1067+
int sig = eloop_sig[--eloop_nsig];
10701068

10711069
if (eloop->signal_cb != NULL)
1072-
eloop->signal_cb(n, eloop->signal_cb_ctx);
1070+
eloop->signal_cb(sig, eloop->signal_cb_ctx);
10731071
continue;
10741072
}
10751073
#endif

src/eloop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ struct eloop *eloop_new(void);
9797
void eloop_free(struct eloop *);
9898
void eloop_exit(struct eloop *, int);
9999
int eloop_forked(struct eloop *, unsigned short);
100+
int eloop_waitfd(int);
100101
int eloop_start(struct eloop *);
101102

102103
#endif

0 commit comments

Comments
 (0)