I rewrote much of the kqueue code since the old code didn't handle properly the case when both input and output I/O handlers were added to the same file descriptor with different callbacks. This is done commonly in Dovecot, so I'm wondering why more people didn't complain about problems with it.. :)
I don't anyway have access to any BSDs so the code is completely untested. Please test how it works before 1.0rc7 :)
http://dovecot.org/nightly/dovecot-latest.tar.gz
I'd guess the hangs caused by recent RC versions were because the default was to use notify=kqueue instead of notify=none. I changed this back to none unless --with-ioloop=kqueue is used.
There are a couple of things in the code that I'm not completely sure of. The kqueue() manual page says that EV_ADD "modifies" the event if it already exists. What exactly does that mean? Does it mean that the filter is replaced, or that it's ORed into the existing one? The same question for the EV_DELETE, does it delete everything or only those filters given in parameters?
The code currently assumes ORing and EV_DELETE deleting only the given filters, since this is what the original code also did.
I suppose the data and udata parameters don't matter in EV_DELETE since they weren't given originally in ioloop-notify-kqueue.c either, so I left them that way.