POPFile と SSL な日々

0.22.0 より追加された SSL 対応機能で、メール受信時に遅延が生じるという問題が起こっているようだ。私の環境では、Mac でも Windows でも再現しないのだが、GLOBAL_timeout で指定された時間だけの遅延が起こる場合があるらしい。すべてのメールで起こるわけではなく、特定のメールで起こるらしい。ログを送ってもらって調べてみたところ、サーバからデータを読み込んだときに、180 バイト目(180 バイトずつ読み込むようになっている)に(たまたま)0x0d がある場合に起こるらしいことがわかった。
その後、さらに調べていくと、POPFile/Module.pm の $slurp_data__{"$handle"}{select}->can_read( $self->global_config_( 'timeout' ) ) でタイムアウトが起こっていることが判明。このために、GLOBAL_timeout で指定された時間だけの遅延が起こっていたのだ。
また、Net/SSLeay.pm には、

If you need to select(2) on the socket, go right ahead, but be warned
that OpenSSL does some internal buffering so SSL_read does not always
return data even if socket selected for reading (just keep on
selecting and trying to read). Net::SSLeay.pm is no different from the
C language OpenSSL in this respect.

との記述があり、これによると、OpenSSL は内部にバッファを持っているため、データが残っていても SSL_read で読み込めない場合があるということが判明。これが can_read がタイムアウトすることと関係があるのだろうか。
内部のバッファにデータがたまっているかどうかは、OpenSSL の SSL_pending という関数で調べることができるようだ。Perl の IO::Socket:SSL にも、pending という関数がある。これだろうか。
ということで、SSL が使用されている場合には pending をチェックして、0 より大きな数字がかえってくればまだデータがあると判定するように書き換えてみたところ、遅延が起こらなくなったという報告をいただいた。これからソースを整理してパッチとして本家に登録する予定。


これまでに調べたことや、検証用のコードについては、POPFile SSL 遅延問題について にまとめている。こういうドキュメントを書くのにも Wiki は非常に便利だ。