Monoceros等で利用される POSIX::Socketのテストが
こける理由のメモ. RTに登録すべきなんだろうけど、手元の環境ではうまくいかないので
ここにメモっておきます(サーバサイドの問題??).
問題となるテスト
t/10send.tの 2つめのテストが通りません(#2となっているテスト)
sub setsockopt_test($) { my ($buflen) = @_; my $sock; my $ret; $sock = _socket(AF_INET, SOCK_DGRAM, 0) or die "socket: $!\n"; my $rv1 = _setsockopt($sock, SOL_SOCKET, SO_RCVBUF, pack("L", $buflen)); my $rv2 = _getsockopt($sock, SOL_SOCKET, SO_RCVBUF, $ret, 4); _close($sock); return (($rv1 != -1) && ($rv2 != -1) && (unpack("L", $ret) == $buflen*2)); } # 2 ok(setsockopt_test("1000"), "setsockopt/getsockopt test");
問題 1
subsockopt_testの returnの最後の式を見ると, setsockopt(SO_RCVBUF)で設定した値の
2倍の値が getsockoptで取得できることになっていますが、これがまず問題です. 2倍の値を
返すのは Linuxの仕様であり, FreeBSD等他の OSではそのような仕様ではなく,
setsockopt(SO_RCVBUF)で設定したバッファ長がそのまま返ります. なので 2倍の値が返って
くることを期待するのは, Linux以外の環境で動作させる場合良くないでしょう.
問題 2
setsockopt(SO_RCVBUF)に指定するバッファ長が短すぎる問題です.
Linuxのコードを確認したところ, setsockopt(SO_RCVBUF)で設定できる値には
下限があります(procfs等で変更できるかと思われますが, 未確認). 下限以下の
値を設定した場合, それは無視され下限の値の 2倍の値が getsockopt(SO_RCVBUF)で
返ることになります. デフォルトでは下限の値は 1000より大きいので, getsockoptから
返る値は 1000でも 2000でもない値となっています. なので数十KB等のサイズに
するのが妥当でしょう(下限の値をあらかじめチェックするというのが本当は
良いと思います).
問題 1だけでは Linuxはパスしますが, 問題 2もあり, 大半の環境でテストを
パスしないという事態になっているという次第です. Linux::Socketだったら
まああれなんでしょうけど, POSIX::となっているので気になりました.
おわりに
github等にコードが置いてないとレポートがめんどくさいので
なんとかならないものでしょうか・・・。