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).
This commit is contained in:
Ariel Abreu 2020-10-07 12:50:08 -04:00
parent 9a94fadf15
commit 3f76738619
No known key found for this signature in database
GPG Key ID: ECF8C2B9E8AD3E6B

View File

@ -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);