In article <B8BBFD48-5C15-11D9-A492-000D9350318C / mva.biglobe.ne.jp>,
  Masatoshi SEKI <m_seki / mva.biglobe.ne.jp> writes:

> 特定のポート番号でTCPServerを一度作って閉じ、すぐに同じポート番号で獲得できる、
>
>>> # という試験だった気がします。(できない時期があったので)
>
>> うぅむ。そんな内容のテストだったとは。
>>
>> それは本質的に race condition になるので、保証されないと考えるべきだと
>> 思います。
>
> そういうわけで削除します。

本質的には削除が正しいと思うんですが、ひとつ疑問があります。

実は手元にかなり確実に Errno::EADDRINUSE が起きる環境があります。
http://www.rubyist.net/~akr/ab/netbsd-2.0/ruby-trunk/

しかし、その環境では

% ruby -rsocket -e '100.times { TCPServer.new(8473).close }'

というのは問題なく終了するのです。
もちろん、8473 が他で使われていない場合ですが。

つまり、閉じてすぐ作るぶんには問題ないわけで、本当は閉じていないのが問
題なんではないかと疑っています。

調べてみると、

class TestDRbReusePort < TestDRbAry
  def setup
    sleep 1.2
    @ext = DRbService.ext_service('ut_port.rb')
    @there = @ext.front
  end
end

というところの sleep 1.2 を消すと、手元の Debian でも確実に EADDRINUSE
になります。

そこで確認したいのですが、ここはソケットを閉じた後に次のテストを行う仕
掛けになっているんでしょうか?

sleep のところをみると、なっていない気がするのですが。

> それはそうなのですが、そういうのを管理するモジュールのテストに近いので
> ちょっと悩ましいです。鋭意努力しますがそれまでの間、timeoutでごまかしても
> 良いでしょうか?

なるほど。なかなか悩ましいですね。

> 遅くなるのはtimeoutがスレッドを生成するからですか?
> それとも失敗したときにtimeoutの時間まで時間がかかってしまうからですか?

失敗した時に時間がかかることを気にしています。

そっか。成功すれば時間はかからないからこの場合は大きな問題はない気がし
て来ました。

考えてみると、(TestDRbReusePort#setup のように) 成功するケースで sleep
するものが問題なわけですね。
-- 
[田中 哲][たなか あきら][Tanaka Akira]