ninix-aya with Kawari8にバグ発見

ninix-ayaとKawari8の組み合わせでバグを発見しました.

POSIX環境(Linxu, FreeBSD, etc.)でkawari8.soがインストールされている事が前提で, 最小の手順での再現方法は次の通りです.

  1. 「ninix-ayaが互換モジュールで対応しているSAORIを利用する」Kawari8ゴーストを2体インストールする.
  2. ninix-ayaから上記のKawari8ゴースト2体を起動する.
  3. 一方のKawari8ゴーストを終了し, 残ったゴーストでSAORI呼び出しを発生させる.(残ったゴーストを別のゴーストに交代させればSAORI unloadが呼ばれるので簡単です.)
  4. Segmentation fault

原因はkawari8.soの中でSHIORIのインスタンスはゴースト毎に個別に存在しているのに, SAORIの呼び出しのためのコールバックへのポインタは4つあるコールバックに対してそれぞれ1つしかなく, SHIORIのアンロード時にNULLで初期化されるためです.

つまり上の再現手順を行なった際に起こる現象は次のようになります.

  • 2体のゴーストに対してそれぞれ別のSHIORIインスタンスであるSHIORI(1), SHIORI(2)が生成される.
  • SAORIコールバックへのポインタに値が書き込まれる. SHIORI(1), SHIORI(2)でそれぞれ書き込みが起きるので後から起動した方が書き込んだ値になっている.
  • ゴーストの終了でSHIORI(1)がアンロードされるとSAORIコールバックへのポインタがNULLに書き換えられる.
  • 残ったSHIORI(2)がSAORIを呼び出そうとするとコールバックがNULLのため落ちる.

修正方法としてはkawari8.soでSHIORIインスタンス毎にSAORIコールバックへのポインタを持つようにするのが一つの方法ですが, 出来ればninix-aya側だけで何とかしたいですね. 少し考えてみます.(どうしても駄目ならKawari8へのパッチを考えます.)

2012/1/14追記: トリッキーですがkawari8.py側での対処方法を考えました. まず, saori_listをクラス変数にしておいて, SAORI呼び出しのコールバック4つの内のsaori_existを除く3つ(saori_load, saori_unload, saori_request)をクラスメソッドに変更してインスタンスとの結合を無くします.(saori_existのみクラスではなくインスタンスに結び付けておく必要があり, 後で述べる様に呼び出される場合が限られるためそのままにします.) Shioriのロード時だけでなくアンロード後にも_kawari8.setcallback()を呼んでコールバックを再登録します. この時saori_existは0を返すダミー関数を登録します.(何故かというと, Kawari8の仕様上この関数はShioriのロード時以外には呼ばれないからです. 次のKawari8ゴーストが起動した場合にはそのゴーストのShioriが自分の持つコールバックで上書きしてくれるので問題ありません.) これで動くはずなので実装してテストしてみます.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です