Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Nov 2019 20:41:47 +0000 (UTC)
From:      Vladimir Kondratyev <wulf@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r355065 - head/sys/compat/linux
Message-ID:  <201911242041.xAOKflXo045533@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: wulf
Date: Sun Nov 24 20:41:47 2019
New Revision: 355065
URL: https://svnweb.freebsd.org/changeset/base/355065

Log:
  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 <iwtcex@gmail.com>
  Reviewed by:	emaste, imp
  MFC after:	1 week
  Differential Revision:	https://reviews.freebsd.org/D22513

Modified:
  head/sys/compat/linux/linux_event.c

Modified: head/sys/compat/linux/linux_event.c
==============================================================================
--- head/sys/compat/linux/linux_event.c	Sun Nov 24 19:18:12 2019	(r355064)
+++ head/sys/compat/linux/linux_event.c	Sun Nov 24 20:41:47 2019	(r355065)
@@ -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_
 	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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911242041.xAOKflXo045533>