[Gauche-devel-jp] Re: 言語ブリッジ間の例外変換

Back to archive index

Shiro Kawai shiro****@lava*****
2005年 5月 21日 (土) 08:52:40 JST


GaucheとObjCがそれぞれ独自に例外チェインを作ってて、
それがinterleaveしてるのがまずいと思います。

例外チェインは例外発生時に必ず順に辿られなければなりません。
Gauche側の例外機構を仮に g_try, g_catch, g_throw, 
ObjC側のそれを o_try, o_catch, o_throw とした場合、
例えば次のコードでは:

  foo () {
    g_try {
      bar()
    }
    g_catch (e) {
    }
  }

  bar () {
    o_try {
      baz()
    }
    o_catch (e) {
    }
  }

  baz () {
    g_throw(e);
  }

g_throwは直接foo()のg_catchへ飛びますから、bar()で設定された
ObjCの例外フレームが飛ばされてしまい、うまく動きません。
ObjCとGaucheの役割が入れ替わっても同じことです。

従って全ての関数において、(1)その時点で一番内側にある例外フレームが
どちらの機構のものであるかが決まっていること (2)その関数から例外を
投げる時は必ず一番内側の機構の例外に変換して投げること、という
原則を守る必要があります。

Gauche側では、Scm_Apply内でひとつGauche側の例外チェインが
作られます (ソース上では user_eval_inner in vm.c)。
疑似コードで書くとこんな感じです。

 Scm_Apply(proc, args) {
   g_try {
     ret = run_vm_with_proc_and_args(proc, args);
   }
   g_catch {
     色々処理
     もしかするとg_throw()するかも
   }
   return ret;
 }

なので、proc実行中に有効な例外機構はGaucheの方になっています。
そこでObjCの例外が投げられると、Scm_Apply内で設定された例外
フレームがクリーンアップされないまま、Scm_Applyの外側に飛んで
しまいます。そこでScm_VMThrowExceptionを呼ぶと、既にマシン
スタック上から削除されたはずの例外フレームを呼びにゆくので
クラッシュします。

解決策としては、GaucheからObjCの世界へ入る箇所全てに、
ObjCの例外をGaucheの例外に変換して投げるコードを入れる、
ということしか思い付きません。一方、ObjCからGaucheを呼ぶ
箇所全てで、Gaucheから来た例外をObjCの例外に変換して投げる
ようにします。

--shiro







Gauche-devel-jp メーリングリストの案内
Back to archive index