socketry / io-event

MIT License
66 stars 15 forks source link

Failing test case for waiting on a reused FD. #69

Closed Math2 closed 1 year ago

Math2 commented 1 year ago

Types of Changes

Contribution

Notes

I think I found another problem. Probably related to the "lazy disarming" optimization.

IIUC, the selector can mistakenly assume that events for a certain FD are already being polled, but they aren't because the FD has been closed and reopened since last time.

The test case works if you comment out local.close.

I think it's triggering some other problem I was investigating, but not sure...

ioquatix commented 1 year ago

IIUC, the selector can mistakenly assume that events for a certain FD are already being polled, but they aren't because the FD has been closed and reopened since last time.

Yeah, I saw some code in libev which was trying to work around this.

ioquatix commented 1 year ago

Here are the notes:

/*
 * general notes about epoll:
 *
 * a) epoll silently removes fds from the fd set. as nothing tells us
 *    that an fd has been removed otherwise, we have to continually
 *    "rearm" fds that we suspect *might* have changed (same
 *    problem with kqueue, but much less costly there).
 * b) the fact that ADD != MOD creates a lot of extra syscalls due to a)
 *    and seems not to have any advantage.
 * c) the inability to handle fork or file descriptors (think dup)
 *    limits the applicability over poll, so this is not a generic
 *    poll replacement.
 * d) epoll doesn't work the same as select with many file descriptors
 *    (such as files). while not critical, no other advanced interface
 *    seems to share this (rather non-unixy) limitation.
 * e) epoll claims to be embeddable, but in practise you never get
 *    a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32).
 * f) epoll_ctl returning EPERM means the fd is always ready.
 *
 * lots of "weird code" and complication handling in this file is due
 * to these design problems with epoll, as we try very hard to avoid
 * epoll_ctl syscalls for common usage patterns and handle the breakage
 * ensuing from receiving events for closed and otherwise long gone
 * file descriptors.
 */

We might need to be more pessimistic about the cache.