Читать его -- особое развлечение. Куда не поглядишь, то обязательно в
кого-то автор кинет камень:
The epoll mechanism deserves honorable mention as the most
misdesigned of the more advanced event mechanisms: mere
annoyances include silently dropping file descriptors,
requiring a system call per change per file descriptor (and
unnecessary guessing of parameters), problems with dup,
returning before the timeout value, resulting in additional
iterations (and only giving 5ms accuracy while select on the
same platform gives 0.1ms) and so on. The biggest issue is fork
races, however - if a program forks then both parent and child
process have to recreate the epoll set, which can take
considerable time (one syscall per file descriptor) and is of
course hard to detect.
Epoll is also notoriously buggy - embedding epoll fds should
work, but of course doesn't, and epoll just loves to report
events for totally different file descriptors (even already
closed ones, so one cannot even remove them from the set) than
registered in the set (especially on SMP systems). Libev tries
to counter these spurious notifications by employing an
additional generation counter and comparing that against the
events to filter out spurious ones, recreating the set when
required. Epoll also erroneously rounds down timeouts, but
gives you no way to know when and by how much, so sometimes you
have to busy-wait because epoll returns immediately despite a
nonzero timeout. And last not least, it also refuses to work
with some file descriptors which work perfectly fine with
"select" (files, many character devices...).
Epoll is truly the train wreck among event poll mechanisms, a
frankenpoll, cobbled together in a hurry, no thought to design
or interaction with others. Oh, the pain, will it ever stop...
While nominally embeddable in other event loops, this feature
is broken in all kernel versions tested so far.
Но и kqueue не отделался:
Kqueue deserves special mention, as at the time of this
writing, it was broken on all BSDs except NetBSD (usually it
doesn't work reliably with anything but sockets and pipes,
except on Darwin, where of course it's completely useless).
Unlike epoll, however, whose brokenness is by design, these
kqueue bugs can (and eventually will) be fixed without API
changes to existing programs. For this reason it's not being
"auto-detected" unless you explicitly specify it in the flags
(i.e. using "EVBACKEND_KQUEUE") or libev was compiled on a
known-to-be-good (-enough) system like NetBSD.
This backend usually performs well under most conditions.
This uses the Solaris 10 event port mechanism. As with
everything on Solaris, it's really slow, but it still scales
very well (O(active_fds)).
While this backend scales well, it requires one system call per
active file descriptor per loop iteration. For small and medium
numbers of file descriptors a "slow" "EVBACKEND_SELECT" or
"EVBACKEND_POLL" backend might perform better.
On the positive side, this backend actually performed fully to
specification in all tests and is fully embeddable, which is a
rare feat among the OS-specific backends (I vastly prefer
correctness over speed hacks).
On the negative side, the interface is bizarre - so bizarre
that even sun itself gets it wrong in their code examples: The
event polling function sometimes returns events to the caller
even though an error occurred, but with no indication whether
it has done so or not (yes, it's even documented that way) -
deadly for edge-triggered interfaces where you absolutely have
to know whether an event occurred or not because you have to
re-arm the watcher.
Fortunately libev seems to be able to work around these