Nginx
自作サーバー
自作サーバーでIOをEPOLLで多重化しようとしていて、 LevelTriggerとEdgeTriggerどちらを使うべきか悩んでいる。 そもそもそれぞれのメリット、デメリットもよく理解できていない状態だが、 それ以上にepoll(7)に記載されている。 「EdgeTriggerを使うならNonBlockingなファイルディスクリプタを使いなさい」という説明がなかなか理解できなかった。
An application that employs the EPOLLET flag should use nonblocking file descriptors to avoid having a blocking read or write starve a task that is handling multiple file descriptors. The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows: (1) with nonblocking file descriptors; and (2) by waiting for an event only after read(2) or write(2) return EAGAIN.
EdgeTriggerで動作させる場合「nonblockingなファイルディスクリプタ(以下fd)を使って、 かつread(2)かwrite(2)がEAGAINだった場合にのみwaitしなさい」という内容だ。 後者のEAGAINだった場合にのみ〜という内容は比較的自明な気がしていて、 read可能なのに次のEdgeの立ち上がりを待ってしまうと。 未来でEdgeが立ち上がらなかった場合、 最初に入っていたデータが放置され続けてしまう。 特に相手が返答を待っている状態だった場合に通信がハングしてしまう。
一方で前者のnonblockingなfdを使うべき、という主張の部分が知識不足で理解できなかったので簡単に調査した。
StackOverflowのこの記事などを参考にした。 おそらく以下のような事象が発生するからだと考えられる。
LevelTriggerでepollを使用し、かつブロッキングでreadするケースを考える。
まとめるとEdgeTriggerを使う場合には以下2点に気をつける必要がある。(1に関してはレベルトリガーも同じな気がする)