概要
「安全なeval」を実現する為には、ステップ実行による「停止問題の回避」だけではなく、「リソース過剰消費」にも対策を行う必要がある。
よって、それを行う為の「eval/memlimit」を実装してみた。
作った感想
- かなり効率が悪い。効率を良くする為には、やっぱりSCM_MALLOC系を差し替えて、そのタイミングでのみリソース量のチェック等を行うようにする必要がある。
- Gauche以外では動かない。
- (gc)と(gc-stat)は非公式っぽい(リファレンスには載ってない)ので、将来も機能する事は保証されない。
- ちょっと大雑把すぎるかも知れない。
- eval/svを利用して実装したので、「eval/memlimit」となっているが、可能なら、これはwith-signal-handlerのように、「with-memlimit」のような形にした方が使いやすい筈。
- 手続きの名前をもうちょっと考え直したい。
要求される仕様
具体的なコードは、上のリンクの「最終状態」のコードを見てください。
- eval/memlimitの場合はS式を、with-memlimitの場合はclosureを第一引数として要求する。
- 第二引数として、消費してもよい最大メモリ量をbyte単位で指定する。
- S式をevalする(またはclosureを実行する)。
- S式のeval(またはclosureの実行)中にメモリ消費、つまりSCM_MALLOC系が実行される度に、「実行中に消費された総メモリ量」を算出する。これが第二引数以下なら実行を続行する。
- 「実行中に消費された総メモリ量」が第二引数を越えていた場合は、一旦(gc)してから、もう一度算出し直す。(gc)によって回復した場合は実行を続行する。
- それでも第二引数を越えていた場合は、継続を辿ってeval/memlimit(またはwith-memlimit)に戻り、その時点からエラー例外を投げる。
- その場でエラー例外を投げると、eval(またはclosure)内で補足されてしまう可能性がある為、一旦継続によって戻る必要がある(eval/svのexceptと同じ)。
改善すべき点
基本的には、「作った感想」と、上のリンクの「最終状態」のところに書いたが、それ以外に、重要な問題が一つ残っている。
- 前述の仕様では、いきなり一つの巨大メモリを要求された時に、GC_oom_fnがScm_Panicを呼んで強制終了する事を防げない。
これを解決しない限りは、「安全なeval」は実現できない。
最終更新 : 2008/04/17 22:10:43 JST