From 896a4c279dbcca744aebd7b40bb62f2de4650b0b Mon Sep 17 00:00:00 2001 From: Vladimir Kondratyev Date: Sun, 24 Nov 2019 20:41:47 +0000 Subject: [PATCH] Linux epoll: Don't deregister file descriptor after EPOLLONESHOT is fired Linux epoll does not remove descriptor after one-shot event has been triggered. Set EV_DISPATCH kqueue flag rather then EV_ONESHOT to get the same behavior. Required by Linux Steam client. PR: 240590 Reported by: Alex S Reviewed by: emaste, imp MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D22513 --- sys/compat/linux/linux_event.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c index f10cccec30a..7d26ee3e505 100644 --- a/sys/compat/linux/linux_event.c +++ b/sys/compat/linux/linux_event.c @@ -306,7 +306,7 @@ epoll_to_kevent(struct thread *td, struct file *epfp, /* flags related to how event is registered */ if ((levents & LINUX_EPOLLONESHOT) != 0) - *kev_flags |= EV_ONESHOT; + *kev_flags |= EV_DISPATCH; if ((levents & LINUX_EPOLLET) != 0) *kev_flags |= EV_CLEAR; if ((levents & LINUX_EPOLLERR) != 0) @@ -501,16 +501,17 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) case LINUX_EPOLL_CTL_ADD: /* * kqueue_register() return ENOENT if event does not exists - * and the EV_ADD flag is not set. + * and the EV_ADD flag is not set. Reset EV_ENABLE flag to + * avoid accidental activation of fired oneshot events. */ - kev[0].flags &= ~EV_ADD; + kev[0].flags &= ~(EV_ADD | EV_ENABLE); error = kqfd_register(args->epfd, &kev[0], td, M_WAITOK); if (error != ENOENT) { error = EEXIST; goto leave0; } error = 0; - kev[0].flags |= EV_ADD; + kev[0].flags |= (EV_ADD | EV_ENABLE); break; case LINUX_EPOLL_CTL_DEL: