svn commit: r295786 - in head: sys/kern tests/sys/kqueue

Mark Johnston markj at FreeBSD.org
Fri Feb 19 01:49:34 UTC 2016


Author: markj
Date: Fri Feb 19 01:49:33 2016
New Revision: 295786
URL: https://svnweb.freebsd.org/changeset/base/295786

Log:
  Ensure that we test the event condition when a disabled kevent is enabled.
  
  r274560 modified kqueue_register() to only test the event condition if the
  corresponding knote is not disabled. However, this check takes place before
  the EV_ENABLE flag is used to clear the KN_DISABLED flag on the knote, so
  enabling a previously-disabled kevent would not result in a notification for
  a triggered event. This change fixes the problem by testing for EV_ENABLED
  before possibly checking the event condition.
  
  This change also updates a kqueue regression test to exercise this case.
  
  PR:		206368
  Reviewed by:	kib
  Sponsored by:	EMC / Isilon Storage Division
  Differential Revision:	https://reviews.freebsd.org/D5307

Modified:
  head/sys/kern/kern_event.c
  head/tests/sys/kqueue/read.c

Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c	Fri Feb 19 01:35:01 2016	(r295785)
+++ head/sys/kern/kern_event.c	Fri Feb 19 01:49:33 2016	(r295786)
@@ -1323,27 +1323,24 @@ findkn:
 	 * kn_knlist.
 	 */
 done_ev_add:
-	if ((kev->flags & EV_DISABLE) &&
-	    ((kn->kn_status & KN_DISABLED) == 0)) {
+	if ((kev->flags & EV_ENABLE) != 0)
+		kn->kn_status &= ~KN_DISABLED;
+	else if ((kev->flags & EV_DISABLE) != 0)
 		kn->kn_status |= KN_DISABLED;
-	}
 
 	if ((kn->kn_status & KN_DISABLED) == 0)
 		event = kn->kn_fop->f_event(kn, 0);
 	else
 		event = 0;
+
 	KQ_LOCK(kq);
 	if (event)
-		KNOTE_ACTIVATE(kn, 1);
+		kn->kn_status |= KN_ACTIVE;
+	if ((kn->kn_status & (KN_ACTIVE | KN_DISABLED | KN_QUEUED)) ==
+	    KN_ACTIVE)
+		knote_enqueue(kn);
 	kn->kn_status &= ~(KN_INFLUX | KN_SCAN);
 	KN_LIST_UNLOCK(kn);
-
-	if ((kev->flags & EV_ENABLE) && (kn->kn_status & KN_DISABLED)) {
-		kn->kn_status &= ~KN_DISABLED;
-		if ((kn->kn_status & KN_ACTIVE) &&
-		    ((kn->kn_status & KN_QUEUED) == 0))
-			knote_enqueue(kn);
-	}
 	KQ_UNLOCK_FLUX(kq);
 
 done:

Modified: head/tests/sys/kqueue/read.c
==============================================================================
--- head/tests/sys/kqueue/read.c	Fri Feb 19 01:35:01 2016	(r295785)
+++ head/tests/sys/kqueue/read.c	Fri Feb 19 01:49:33 2016	(r295786)
@@ -124,15 +124,17 @@ test_kevent_socket_disable_and_enable(vo
 
     test_begin(test_id);
 
-    /* Add an event, then disable it. */
-    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
-    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
-        err(1, "%s", test_id);
-    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]);
+    /*
+     * Write to the socket before adding the event. This way we can verify that
+     * enabling a triggered kevent causes the event to be returned immediately.
+     */
+    kevent_socket_fill();
+
+    /* Add a disabled event. */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISABLE, 0, 0, &sockfd[0]);
     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
         err(1, "%s", test_id);
 
-    kevent_socket_fill();
     test_no_kevents();
 
     /* Re-enable the knote, then see if an event is generated */


More information about the svn-src-all mailing list