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
This commit is contained in:
parent
1945f66461
commit
32d1c3375a
@ -1323,27 +1323,24 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
|
||||
* 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:
|
||||
|
@ -124,15 +124,17 @@ test_kevent_socket_disable_and_enable(void)
|
||||
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user