From 3f76738619904c3f9db728651ca335582f25e09d Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Wed, 7 Oct 2020 12:50:08 -0400 Subject: [PATCH] Handle race condition when waiting for events If multiple threads are waiting on the same kqueue, they'll all be woken up at the same time, however only one can acquire the lock at a time. The one that acquires it first gets to consume some events from the kqueue while everyone else waits. But, after they're done and they release the lock, the next person will have *less events available*. We were previously neglecting to check for this and trying to consume more events than were available (leading to some nasty deadlocks with certain events like EVFILT_USER). --- src/common/kevent.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/common/kevent.c b/src/common/kevent.c index 7cabdea..ceb385d 100644 --- a/src/common/kevent.c +++ b/src/common/kevent.c @@ -389,7 +389,16 @@ again: kqueue_lock(kq); if (fastpath(rv > 0)) { - rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); + // we might have raced for an event... + // since we had to acquire the lock, we might have lost the race, + // so check again (non-blockingly) to see if we still have any events + rv = kqops.kevent_wait(kq, nevents, &timeout_zero); + + if (fastpath(rv > 0)) { + rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); + } else { + dbg_puts("lost the race!"); + } } kqueue_cleanup(kq);