Skip to content

Commit

Permalink
Keep a separate state tree for file descriptors inserted into epoll t…
Browse files Browse the repository at this point in the history
…o avoid conflicts between EVFILT_READ and EVFILT_WRITE Closes mheily#29 Closes mheily#59

There's more work required, but at least this fixes the outstanding issues.

Known limitations:
- Need to verify correct behaviour of EV_DISPATCH when both filters are registered for events.  This now needs to be implemented internally by libkqueue instead of relying on EPOLLET, as EPOLLET applies to both EPOLLIN and EPOLLOUT.

- If the number of events we are to return does not have sufficient space for at least two entries when polling an FD registered for both read and write events, the write event will be lost.  We can fix this by implementing a linked list of pending events we return before calling the platform's wait function. Will probably copy the dlist implementation from FreeRADIUS across, as it's been well tested, and is a header only implementation like the current rbtree. A dlist is needed to store entries for EVFILT_PROC anyway, which is the next filter that needs major attention.
  • Loading branch information
arr2036 authored and ghostmansd committed Apr 28, 2021
1 parent 6f83821 commit 62f7e55
Show file tree
Hide file tree
Showing 10 changed files with 645 additions and 170 deletions.
4 changes: 2 additions & 2 deletions src/common/kevent.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,12 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src)
rv = knote_delete(filt, kn);
dbg_printf("knote_delete returned %d", rv);
} else if (src->flags & EV_DISABLE) {
kn->kev.flags |= EV_DISABLE;
rv = filt->kn_disable(filt, kn);
if (rv == 0) kn->kev.flags |= EV_DISABLE;
dbg_printf("kn_disable returned %d", rv);
} else if (src->flags & EV_ENABLE) {
kn->kev.flags &= ~EV_DISABLE;
rv = filt->kn_enable(filt, kn);
if (rv == 0) kn->kev.flags &= ~EV_DISABLE;
dbg_printf("kn_enable returned %d", rv);
} else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) {
kn->kev.udata = src->udata;
Expand Down
21 changes: 10 additions & 11 deletions src/common/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ struct knote {
*
*/
struct filter {
short kf_id; //!< EVFILT_* facility this filter provides.
short kf_id; //!< EVFILT_* facility this filter provides.

/* filter operations */

Expand All @@ -151,20 +151,19 @@ struct filter {


int (*kn_create)(struct filter *, struct knote *);
int (*kn_modify)(struct filter *, struct knote *,
const struct kevent *);
int (*kn_modify)(struct filter *, struct knote *, const struct kevent *);
int (*kn_delete)(struct filter *, struct knote *);
int (*kn_enable)(struct filter *, struct knote *);
int (*kn_disable)(struct filter *, struct knote *);

struct eventfd kf_efd; /* Used by user.c */
struct eventfd kf_efd; //!< Used by user.c

//MOVE TO POSIX?
int kf_pfd; /* fd to poll(2) for readiness */
int kf_wfd; /* fd to write when an event occurs */
int kf_pfd; //!< fd to poll(2) for readiness
int kf_wfd; //!< fd to write when an event occurs
//----?

struct evfilt_data *kf_data; /* filter-specific data */
struct evfilt_data *kf_data; //!< filter-specific data */
RB_HEAD(knt, knote) kf_knote;
pthread_rwlock_t kf_knote_mtx;
struct kqueue *kf_kqueue;
Expand All @@ -182,10 +181,10 @@ struct filter {
* in receiving notifications for.
*/
struct kqueue {
int kq_id; //!< File descriptor used to identify this kqueue.
struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each
///< kqueue maintains one filter state structure
///< per filter type.
int kq_id; //!< File descriptor used to identify this kqueue.
struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each
///< kqueue maintains one filter state structure
///< per filter type.
fd_set kq_fds, kq_rfds;
int kq_nfds;
tracing_mutex_t kq_mtx;
Expand Down
Loading

0 comments on commit 62f7e55

Please sign in to comment.