この辺を確認するために、今回調べてみようと思う。
連続耐久試験
当然、安定して動作しないと使えないということで、たくさんの要求を出してみる検証を行った。
修正ソース
require 'drb/drb' url = ARGV[0] p url q = DRbObject.new_with_uri(url) 1000.times do q.add_request( :func1 , [12,34] ) end
結果
C:\work>\ironruby-0.9.2\bin\ir.exe druby\client_2.rb druby://127.0.0.1:1495
"druby://127.0.0.1:1495"
C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:580:in `load': premature marshal format(can't read) (DRb::DRbConnError)
from C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:633:in `recv_reply'
from C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:921:in `recv_reply'
from C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:1195:in `send_message'
from C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:1086:in `method_missing'
from C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:1170:in `open'
from C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:1085:in `method_missing'
from C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:1102:in `with_friend'
from C:/ironruby-0.9.2/lib/ruby/1.8/drb/drb.rb:1084:in `method_missing'
from druby/client_2.rb:8
from druby/client_2.rb:7
from :0:in `times'
5回目くらいの要求発行で例外発生!?えっ!えっ!該当部分のソースをみてみると
begin str = soc.read(sz) rescue raise(DRbConnError, $!.message, $!.backtrace) end raise(DRbConnError, 'connection closed') if str.nil? raise(DRbConnError, 'premature marshal format(can\'t read)') if str.size < sz
一番下の部分で例外が出ている。つまり、読み込んだサイズと読み込まれるべきサイズの差があるようだ。
基礎実験開始
サーバ側ソース
require "socket"
gs = TCPServer.open('127.0.0.1',12345)
socks = [gs]
addr = gs.addr
addr.shift
printf("server is on %s\n", addr.join(":"))
loop do
nsock = select(socks)
next if nsock == nil
for s in nsock[0]
if s == gs
socks.push(s.accept)
print(s, " is accepted\n")
else
if s.eof?
print(s, " is gone\n")
s.close
socks.delete(s)
else
ls = s.read(4)
p ls.size
num = ls.unpack("I")
p num
str = s.read(num[0])
p str.size
p s.write(str*20)
end
end
end
end
クライアント側ソース
require "socket"
s = TCPSocket.open("127.0.0.1", 12345)
c='a'
100000.times do |i|
num = rand(1000)+1
c = '%c' % ("0123456789"[i%10])
wr4 = s.write([num].pack('I'))
wrn = s.write(c*num)
r = s.read(num*20)
puts "#{(num*20 == r.size).inspect}\t#{c} #{r[0]} #{r[1]} #{num} #{r.size} #{wr4}(4) #{wrn}"
exit unless num*20 == r.size
end
s.close
MRI および IronRuby 0.9.2 で動作するぞ。
最初 socke.read( request_size ) の request_size 指定分読み込めないのかと思った。 rubyのsocket.read は指定されたサイズ到着までブロックするはずであり、ブロック抜けてきたという事は、そのサイズ分到着したということである。その到着したはずなのに差があるということで例外が出ているのかと思い、上記の基本プログラムで動作を確認した。
そうしたところ、その挙動をしている。IronRuby 0.9.2 の バグかと思っていたが、そうではなさそうだ
IronRuby と MRI 間通信
試しに、先ほどの druby通信のクライアント側を IronRuby 0.9.2 / サーバ側を ruby 1.8.7 で行ったところ、無事通信ができている
またdruby通信のクライアント側を ruby 1.8.7 / サーバ側を IronRuby 0.9.2で行ったところ、無事通信ができている
これはまた謎が深まってきた
まとめ
これをまとめると、何らかのタイミングなどを含むバグがあるみたいである。この辺を解明しないと、昼もぐっすり眠れないかもしれない。


コメントする