The manpages of kqueue(2) and kevent(2) are difficult to understand and potentially underspecified. In particular: 1. It is not elaborated what is the purpose of EV_ENABLE and EV_DISABLE in comparison to temporarily deleting an event with EV_DELETE. Is it just a performance issue or are there other effects when disabling an event temporarily with EV_DISABLE (or EV_DISPATCH) opposed to using EV_DELETE (or EV_ONESHOT). 2. What does EV_RECEIPT exactly do? What does the phrase "remaining space in eventlist" refer to? Is it necessary and sufficient(!?) that the output buffer has the exact same length as the number of elements in the input buffer that have EV_RECEIPT set when doing bulk changes and wanting to avoid draining other potentially pending events? This is not clarified. 3. What is the purpose of not specifying EV_CLEAR for those events where it's not implicitly enabled? How long would an event be reported as pending? Until the event is disabled? Until the event is deleted? Is there any way to "acknowledge" the event? And which events in particular "report state transitions instead of the current state", i.e. for which events is EV_CLEAR particularly useful and how is it useful? 4. The list of flags does not distinguish between input and output flags. This also has caused previous confusion in the example code (#240015). Is it correct that a flag is either used as an input flag (in changelist[]) or as an output flag (in eventlist[]), or is there a case when a flag can be set in either of those? Why are there not two lists for flags in the manpage: one for the input flags and one for the output flags? 5. Monitoring a process to exit (using EVFILT_PROC with NOTE_EXIT) results in the process' exit status (that may be checked with WIFEXITED and related macros) to be returned in the data field of the struct kevent in the eventlist. However, the manpage is unclear about whether the process' status is collected or not; i.e. it is unclear if zombie processes would be created if that status in the data field is used and there is no further call to waitpid(). According to my tests, zombies would be created if waitpid() is not explicitly invoked. If that is the case, it should be clarified in the manpage. 6. If an EVFILT_PROC / NOTE_EXIT event fires, the event seems to be automatically removed from the queue, i.e. a subsequent EV_DELETE would return with an ENOENT error. Thus, the behavior seems to be like EV_ONESHOT is explicitly set. While this behavior may be useful, it is not documented and thus could result in unexpected errors. 7. The section on EVFILT_TIMER does not specify which timer is used for absolute times (NOTE_ABSTIME), i.e. whether CLOCK_REALTIME, CLOCK_MONOTONIC, or CLOCK_UPTIME is used. The manpage speaks of "non-monotonic timers". Does this mean NOTE_ABSTIME uses CLOCK_MONOTONIC? Or does it refer to relative timers (where CLOCK_MONOTONIC is used internally)? When exactly is a timer "non-monotonic" and what does that mean? What effect does the (then implicitly set) EV_CLEAR flag have on timers? Overall, it's currently very hard to use kqueue/kevent solely based on the information on the manpage. This issue report has been filed after I asked on the forum about it: https://forums.freebsd.org/threads/how-to-use-kevent-confused-by-manpage.92419/
As I see it, the way forward is to break this up into smaller pieces and submit a patch for each one. I suspect each type likely deserves a separate document - which can be linked from the main kqueue / kevent mandoc page. Attaching bits of sample code illustrating observed behavior is extemely helpful to the review process. Along these lines, I'd like to add my two cents on documenting how to watch files and directories (VNODEs). For example, the read and write events on a directory don't tell you what changed, only that - in the case of a write - something changed. The best I can determine is you need to take a snapshot of the directory and, upon receiving a write event, re-read the directory and compare to see what changed. It would be nice if the read and write events gave us some sort of identity as a clue to what changed. Maybe place the top inode of the directory entry than changed into the ext[] data, for example.
About EV_CLEAR - I've read that someone kept getting the same event over and over until they updated the subscription to include EV_CLEAR.
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=240015 looks like low-hanging fruit (delete to lines from existing docs).