linux_kevent_wait_hires() only reports the epoll descriptor
itself as ready, not the descriptors epoll is actually watching.
We still need to call epoll_wait with timeout=0 to populate the
epevt array.
This fixes a bug where epevt is unpopulated while nret > 0,
leading the eventual call of linux_kevent_copyout() to segfault.
---
This patch is also available for download at:
http://bogomips.org/libkqueue.git/patch?id=8fb20b732f
src/linux/platform.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/linux/platform.c b/src/linux/platform.c
index 056fb0a..097b3ad 100644
--- a/src/linux/platform.c
+++ b/src/linux/platform.c
@@ -123,22 +123,24 @@ linux_kevent_wait(
/* Use pselect() if the timeout value is less than one millisecond. */
if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec < 1000000) {
nret = linux_kevent_wait_hires(kq, ts);
+ if (nret <= 0)
+ return (nret);
- /* Otherwise, use epoll_wait() directly */
+ /* pselect() told us epoll_wait() should have ready events */
+ timeout = 0;
} else {
-
/* Convert timeout to the format used by epoll_wait() */
if (ts == NULL)
timeout = -1;
else
timeout = (1000 * ts->tv_sec) + (ts->tv_nsec / 1000000);
+ }
- dbg_puts("waiting for events");
- nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout);
- if (nret < 0) {
- dbg_perror("epoll_wait");
- return (-1);
- }
+ dbg_puts("waiting for events");
+ nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout);
+ if (nret < 0) {
+ dbg_perror("epoll_wait");
+ return (-1);
}
return (nret);
--
Eric Wong