epoll: Fix event clobber
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 27 Sep 2016 15:48:51 +0000 (11:48 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 6 Oct 2016 19:41:48 +0000 (15:41 -0400)
It was possible, though I never saw it, for an event entry to be clobbered.
Say we extracted a CEQ message for a particular FD.  That set the events
field in the epoll_event.  Then we attempt to extract another CEQ message,
possibly intending for another FD in the epoll set.  Instead, we get
another message for that same FD that we already set an event for.  When we
set that event, we clobber the original one.

The fix is to accumulate events for a given FD for all CEQ messages.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/iplib/epoll.c

index 1a1d03d..4af62e5 100644 (file)
@@ -442,7 +442,8 @@ static bool get_ep_event_from_msg(struct epoll_ctlr *ep, struct event_msg *msg,
                return FALSE;
        }
        ep_ev->data = ep_fd->ep_event.data;
-       ep_ev->events = taps_to_ep_events(msg->ev_arg2);
+       /* The events field was initialized to 0 in epoll_wait() */
+       ep_ev->events |= taps_to_ep_events(msg->ev_arg2);
        return TRUE;
 }
 
@@ -516,7 +517,7 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents,
                int timeout)
 {
        struct epoll_ctlr *ep = fd_to_cltr(epfd);
-       int ret;
+
        if (!ep) {
                errno = EBADF;/* or EINVAL */
                return -1;
@@ -525,8 +526,9 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents,
                errno = EINVAL;
                return -1;
        }
-       ret = __epoll_wait(ep, events, maxevents, timeout);
-       return ret;
+       for (int i = 0; i < maxevents; i++)
+               events[i].events = 0;
+       return __epoll_wait(ep, events, maxevents, timeout);
 }
 
 int epoll_pwait(int epfd, struct epoll_event *events, int maxevents,