diff --git a/src/kqueue.rs b/src/kqueue.rs index 8af4f4b..727c83f 100644 --- a/src/kqueue.rs +++ b/src/kqueue.rs @@ -470,14 +470,17 @@ mod notify { /// Notifies the `Poller`. pub(super) fn notify(&self, poller: &Poller) -> io::Result<()> { - // Trigger the EVFILT_USER event. + // Trigger the EVFILT_USER event. EV_CLEAR must be + // preserved so the event auto-resets after delivery; + // without it EV_ADD would switch the filter to + // level-triggered mode and subsequent waits would spin. poller.submit_changes([kqueue::Event::new( kqueue::EventFilter::User { ident: 0, flags: kqueue::UserFlags::TRIGGER, user_flags: kqueue::UserDefinedFlags::new(0), }, - kqueue::EventFlags::ADD | kqueue::EventFlags::RECEIPT, + kqueue::EventFlags::ADD | kqueue::EventFlags::RECEIPT | kqueue::EventFlags::CLEAR, crate::NOTIFY_KEY as _, )])?; diff --git a/src/lib.rs b/src/lib.rs index 7ae8eb5..8bb049f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -759,6 +759,11 @@ impl Poller { // If the wait was interrupted by a signal, clear events and try again. if e.kind() == io::ErrorKind::Interrupted { events.clear(); + // Reset the notification flag so a concurrent + // notify() call whose EVFILT_USER event was + // consumed by the interrupted kevent() can + // re-trigger. + self.notified.swap(false, Ordering::SeqCst); continue; } else { return Err(e);