Date: Fri, 19 Feb 2016 01:49:33 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r295786 - in head: sys/kern tests/sys/kqueue Message-ID: <201602190149.u1J1nXnT092751@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201602190149.u1J1nXnT092751>