Index: sys/compat/linux/linux_event.c =================================================================== --- sys/compat/linux/linux_event.c +++ sys/compat/linux/linux_event.c @@ -262,12 +262,10 @@ static void kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event) { - l_event->data = kevent->ext[0]; if ((kevent->flags & EV_ERROR) != 0) { l_event->events = LINUX_EPOLLERR; - return; } /* XXX EPOLLPRI, EPOLLHUP */ @@ -281,6 +279,20 @@ l_event->events = LINUX_EPOLLOUT; break; } + + /* Handle all events to meet all Linux epoll cases */ + if ((kevent->pevents & EV_POLLIN) != 0) { + l_event->events |= LINUX_EPOLLIN; + } + if ((kevent->pevents & EV_POLLHUP) != 0) { + l_event->events |= LINUX_EPOLLHUP; + } + if ((kevent->pevents & EV_POLLRDHUP) != 0) { + l_event->events |= LINUX_EPOLLRDHUP; + } + if ((kevent->pevents & EV_POLLRDNORM) != 0) { + l_event->events |= LINUX_EPOLLRDNORM; + } } /* Index: sys/kern/uipc_socket.c =================================================================== --- sys/kern/uipc_socket.c +++ sys/kern/uipc_socket.c @@ -3830,6 +3830,12 @@ kn->kn_data = sbavail(&so->so_rcv) - so->so_rcv.sb_ctl; if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; + if (so->so_snd.sb_state & SBS_CANTSENDMORE) { + kn->kn_pevents |= EV_POLLHUP; + } else { + kn->kn_pevents |= + EV_POLLIN | EV_POLLRDHUP | EV_POLLRDNORM; + } kn->kn_fflags = so->so_error; return (1); } else if (so->so_error) /* temporary udp error */ @@ -3875,6 +3881,9 @@ if (so->so_snd.sb_state & SBS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; + if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { + kn->kn_pevents |= EV_POLLHUP; + } kn->kn_fflags = so->so_error; return (1); } else if (so->so_error) /* temporary udp error */ Index: sys/sys/event.h =================================================================== --- sys/sys/event.h +++ sys/sys/event.h @@ -33,6 +33,7 @@ #include #include +#include #define EVFILT_READ (-1) #define EVFILT_WRITE (-2) @@ -58,6 +59,7 @@ .fflags = (d), \ .data = (e), \ .udata = (f), \ + .pevents = 0, \ .ext = {0}, \ }; \ } while(0) @@ -73,10 +75,10 @@ (kevp)->fflags = (d); \ (kevp)->data = (e); \ (kevp)->udata = (f); \ + (kevp)->pevents = 0; \ (kevp)->ext[0] = 0; \ (kevp)->ext[1] = 0; \ (kevp)->ext[2] = 0; \ - (kevp)->ext[3] = 0; \ } while(0) #endif @@ -87,7 +89,8 @@ unsigned int fflags; /* filter flag value */ __int64_t data; /* filter data value */ void *udata; /* opaque user data identifier */ - __uint64_t ext[4]; /* extensions */ + __uint64_t pevents; /* poll events, used to Linux epoll */ + __uint64_t ext[3]; /* extensions */ }; #if defined(_WANT_FREEBSD11_KEVENT) @@ -153,6 +156,16 @@ #define EV_EOF 0x8000 /* EOF detected */ #define EV_ERROR 0x4000 /* error, data contains errno */ +/* poll event */ +#define EV_POLLIN POLLIN +#define EV_POLLPRI POLLPRI +#define EV_POLLOUT POLLOUT +#define EV_POLLERR POLLERR +#define EV_POLLHUP POLLHUP +#define EV_POLLRDNORM POLLRDNORM +#define EV_POLLRDHUP 0x00002000 + + /* * data/hint flags/masks for EVFILT_USER, shared with userspace * @@ -311,6 +324,7 @@ #define kn_fflags kn_kevent.fflags #define kn_data kn_kevent.data #define kn_fp kn_ptr.p_fp +#define kn_pevents kn_kevent.pevents }; struct kevent_copyops { void *arg;