OpenBSD でデーモンを書いてて気づいたんですが、kqueue のファイルデスクリプタはプロセス間で共有できない、つまり、fork(2) で子プロセスに継承されたり SCM_RIGHTS で投げつけたりすることはできないんですね。
OpenBSD 5.2 の kqueue(2) man ページには
kqueue() creates a new kernel event queue and returns a descriptor. The queue is not inherited by a child created with fork(2). Similarly, kqueues cannot be passed across UNIX-domain sockets.
とあります。イベントがもらえてもファイルデスクリプタテーブルは別なので kqueue のファイルデスクリプタだけ持っててもしょうがないですね。
kqueue を直接使うのではなく libevent 経由で使っていたのですが、libevent が kqueue を使う環境で daemon(3) を呼ぶ前に event_base_new() を呼ぶとこの制限に引っかかって期待した動作をしなくなります。
FreeBSD ではどうかというと、OpenBSD と基本的には同じですが、rfork(2) という「fork() するけど子プロセスといくつかのリソースを共有する」システムコールがあって、それでファイルデスクリプタテーブルを共有するようにした場合は kqueue も共有されるようです。実際に挙動を確かめてはいません。
Linux には似た機構として epoll(2) がありますが、こっちは epoll のファイルデスクリプタ自体は共有することができるようです。ただし、「意味がない」と書かれています。
- Q5
- Can I send an epoll file descriptor over a Unix domain socket to another process?
- A5
- Yes, but it does not make sense to do this, since the receiving process would not have copies of the file descriptors in the epoll set.
というわけで、event_base_new() は daemon(3) の後に呼ぶ必要があるわけですが、プログラム内でいろいろと依存関係がありまして、さてどうしようかな。
# select や poll を使うように設定するというのはナシで
no comment untill now