現在開発中のFunnelはI/Oモジュールとシリアルで、クライアントとOSCでやり取りするサーバをRubyで書いています。おおむねいい感じで動いているのですが、ちょっと思ったようなパフォーマンスが出ていないため、プロファイリングをしてみようと思いました。とりあえず標準で入っているもので…と試してみると、segmentation faultで落ちてしまいました。
$ ruby -r profile funnel_server.rb
...
./gainer_io.rb:331: [BUG] Segmentation fault
ruby 1.8.2 (2004-12-25) [universal-darwin8.0]
Abort trap
このメッセージに関していろいろと調べていると、少し前のRubyist Magazineに記事がありました。この記事で、Arrayに関して長さが変わるような操作をした時に不具合が起きる可能性があるということはわかりました。しかし、今回の場合、問題の箇所では
@din_ports.times {|i| @input[offset + i] = val[i]}
のようにしているだけで、特に長さが変わるような処理をしているわけではありません。また、profileやdebugなどのオプションをつけない限りは、特に問題なく動き続けます。あれこれとコードを変更して試していったのですが、毎回微妙に落ちる箇所が変わったりして、なんとも原因がつかめません。すっかりはまってしまって3時間ほどあれこれ仮説を立てて試しましたが、断念して休憩にしました。
ここでふと気がついたのですが、この部分はシリアルポートからのデータを受信しているスレッドの一部で、38400bpsでフルレートの60%以上でデータが流れ続けてくる、という部分です。プロフィラやデバッガが動作することで処理が処理が間に合わなくなったことが原因で起きているのでは?というところでひとまず保留にしました。いくつか高速なプロファイラもリリースされているようですので、それらに入れ替えて再現性などを確認してみようと思います。
Rubyに限らずの話ですが、調子良く動いている間はスクリプト言語はとても快適なのですが、おかしくなった時にはかなり不安になりますね…。経験の問題が大きいと思うのですが…。
コメント