2007年10月28日
スクリプトエラーのリカバリー
あるときから、麻雀のHUDの中のスクリプトの1本(majan_find_useless_pai.lsl)が、Heap エラーで止まるようになりました。そのスクリプトは手牌の聴牌や、ツモ上がりを検出するスクリプトです。止まってしまっても、ゲームの進行は続くのですが、スクリプトが止まってしまったHUDをつけている人は、ツモ上がりやリーチが掛けられなくなります。

問題のスクリプトをリセットできれば、問題は解決します。また、当該スクリプトが止まっていることは、llMessageLinked()のメッセージの有無を観測することで、チェックができます。他のスクリプトから問題のスクリプトを llResetOtherScript() でリセットがかけられればよいのですが、llResetOtherScript() は、
This currently does not reset a script that stopped with a run-time error (like a stack-heap collision or a bounds check error), so it's of limited use.
となっていて、エラーで止まったスクリプトにリセットをかけることが出来ません。そのかわりに
llRemoteLoadScriptPin()が使えそうです。他のプリムの中に、エラーを起こすスクリプトをrunningのチェックを外した状態で置きます。さらにルートプリム中のmajan_find_useless_pai.lslが動作しているかチェックし、動いていないことを検出したら、llRemoteLoadScriptPin()で止まってしまったスクリプトを上書きし、running状態にするスクリプト(hud_alive.lsl)を設置しました。エラーで止まってしまっても、ツモが一巡以内に検出し、スクリプトを再スタートさせ、無事に続行できることが確認できました。

もっとも、こんな手法に頼らずに、Heap Error が起きないように組めればよいのですが、どこでHeap Errorが出ているのか、皆目見当がついていません。listで全く関係のないアドレスを参照している、というのが一番濃厚・・・。

問題のスクリプトをリセットできれば、問題は解決します。また、当該スクリプトが止まっていることは、llMessageLinked()のメッセージの有無を観測することで、チェックができます。他のスクリプトから問題のスクリプトを llResetOtherScript() でリセットがかけられればよいのですが、llResetOtherScript() は、
This currently does not reset a script that stopped with a run-time error (like a stack-heap collision or a bounds check error), so it's of limited use.
となっていて、エラーで止まったスクリプトにリセットをかけることが出来ません。そのかわりに
llRemoteLoadScriptPin()が使えそうです。他のプリムの中に、エラーを起こすスクリプトをrunningのチェックを外した状態で置きます。さらにルートプリム中のmajan_find_useless_pai.lslが動作しているかチェックし、動いていないことを検出したら、llRemoteLoadScriptPin()で止まってしまったスクリプトを上書きし、running状態にするスクリプト(hud_alive.lsl)を設置しました。エラーで止まってしまっても、ツモが一巡以内に検出し、スクリプトを再スタートさせ、無事に続行できることが確認できました。

もっとも、こんな手法に頼らずに、Heap Error が起きないように組めればよいのですが、どこでHeap Errorが出ているのか、皆目見当がついていません。listで全く関係のないアドレスを参照している、というのが一番濃厚・・・。
Posted by Chiyosuke Wise at 15:02│Comments(1)
│スクリプト
この記事へのコメント
ヒープエラーって言うのは、
関数の戻り先を記憶しているバッファのオーバーフローっぽいよね。
だとすると、イベントが何か別の関数を呼んで、
値をセットした為に、予想外の別のイベントが発生させられたり
ってことが多いよね。
後、自分で自分の関数を呼んだり、関数呼びが無限ループしてたり、
LSLもステップ実行できたり、オンエラーでジャンプできると
いいんだけどね。
関数の戻り先を記憶しているバッファのオーバーフローっぽいよね。
だとすると、イベントが何か別の関数を呼んで、
値をセットした為に、予想外の別のイベントが発生させられたり
ってことが多いよね。
後、自分で自分の関数を呼んだり、関数呼びが無限ループしてたり、
LSLもステップ実行できたり、オンエラーでジャンプできると
いいんだけどね。
Posted by VtWin at 2007年10月28日 16:00