きりかノート 3冊め

おあそびプログラミング

rubycocoa-devel 1202 の調査

もう1ヶ月近く前になるけれど、[rubycocoa-devel:1202] で「Tiger で動いていたプロジェクトが Leopard で動かなくなった」という投稿があって、その時点の trunk では動いたのでそれを報告して「あとで詳しいことは調べとく」ということにした。

で、ちょっと時間とれたので調べた。trunk で動くからほっといても大丈夫かもしれないけれど、原因がわからないと本当に問題がないかはあやしいものだからね。

問題の状況と発生理由がどうも推測できない(ChangeLog を見てもアタリがつかない)ので、リビジョンを変えつつ実行して、問題の修正されたリビジョンを特定するという二分探索を行った。リポジトリ全体にリビジョン番号付く Subversion に移行してあって良かった。CVS でも同じようなことはできるけど、ちょっと手間だもんな。

手順は次のとおり。

  1. てきとうなリビジョンにさかのぼる(svn update -rNNNN)
  2. そのままだと Leopard でビルドできないので r2094:2095 の RBRuntime.m の変更をパッチとして適用
  3. ソースから RubyCocoa.framework をビルドし DYLD_FRAMEWORK_PATH で読み込ませて再現コードを実行

ということを繰り返して、r2058 で修正されたということがわかった。最後は ChangeLog 見て省略できたけど。

r2058の変更は、Ruby 側で生成された Cocoa オブジェクトのメモリ管理に関する変更(ChangeLog 見るかぎり、修正ではなく改善)。どうもこの変更前では、再現コードではオブジェクトが参照中にもかかわらず開放されてしまうということが起こっていたようだ。けっこーマズイ問題。RubyCocoa の次のバージョンがリリースされたら、ぜったいアップデートすべきなんだけど、今までの MacOS X を見ているとソフトウェアアップデートではバージョン上がらないんじゃなかろうか。

ついでに sample/Scripts/darkroom.rb が Leopard 組み込みの RubyCocoa で動かないってのも調べた。これは、LeopardRubyCocoa-57 固有の問題みたいで、SourceForge の 0.12.0 (r2001) から最新の trunk (r2138) まで再現できなかった。これはもう調べない。

(2007/11/24 追記)

これ、テストで発見できないのか?だとしたら今のテストに追加しないといかんな。とりあえず r2057 でテスト実行。

   1) Failure:
test_rbobject_gc(TC_SubClass) [./tc_subclass.rb:249]:
<10000> expected but was
<10001>.

360 tests, 2114 assertions, 1 failures, 0 errors

これか。

このテストケースは、Rubyで定義した Cocoa のサブクラスのインスタンスを 10,000 個生成して、GC でファイナライザが呼ばれた回数を検証するというもの。検証対象の値が期待されるものより大きいということは、release/dealloc が呼ばれすぎってことだ。