仙石浩明の日記

2006年7月14日

stone 2.3b のバグ

重大なバグが発見されない限り正式リリースとする予定だった stone 2.3b であるが、 あいにくバグが発見されてしまった。 SSL 接続が確立する前に TCP 接続が切れてしまうと、 まれに busy loop が発生する。 某環境では、health check と称して ;-( ごく短い時間でポートのオープン/クローズを繰り返しているので、 何日か走らせると load average が無駄に 1 増えてしまっていた。 逆に言うと、かなり無茶な使い方をしない限り、この現象は起きないと思われる。

なぜ busy loop が起きるかと言えば、 doReadWrite() select loop において、 close 予定のソケットについて書込み待ち FD_SET して select(2) を行なうケースがあったからだ。 close 予定のソケットだから、書込み可能でも何も書込まない。 だから select(2) は待ち時間 0 で常に書込み可能を返す。 これが延々繰り返される。

この現象を回避するには、 close 予定のソケットについては FD_SET しなければよい。 ただし SSL_shutdown(3) が書込み待ちでブロックすることがあるので、 この場合、すなわち sf_sb_on_w (SSL flag: shutdown blocked on write) が セットされているときは、 close 予定であっても FD_SET する。 stone.c 2.2.3.6 で修正済み。 なお、busy loop は select 版でのみ確認したが、 epoll 版でも発生する可能性があると思われる。 今回の修正で epoll 版でも busy loop を防ぐことができると思われる。

ついでに、busy loop が起きたときにそれを検知するコードも追加した。 doReadWrite() select loop において busy loop が発生すると、 「<sd> TCP <sd>: doReadWrite Can't happen spin occured」 というエラーログを出力する。 stone が出力するログで「Can't happen」から始まるものは、 想定外の事象が起きたことを示す。 つまりバグである。 stone の最新版において、このようなログに遭遇したかたは、 ご連絡頂けると大変ありがたい。

Filed under: stone 開発日記 — hiroaki_sengoku @ 12:04

コメントはまだありません »

コメントはまだありません。

この投稿へのコメントの RSS フィード。

コメントする