インポート、CPU 時間、および割り当てられたバイトを制限することでユーザー関数を安全に実行できるように、Janino を使用してスクリプト サンドボックスを構築しようとしています。
Rhino (javascript コード用) には、環境を構築するときにユーザーがXを定義できるX命令 ごとに呼び出される、observeInstructionCount(Context ctx, int instructionCount)という名前の関数があります。
この関数では、次のようなことができます。
/**
* This method is called every {@code instructionsBeforeObserve} and it is
* used to check if the current execution has exceded the {@code maxCpuTime}
* or the {maxMemory}. If so, an {@link java.lang.Error} is thrown.
*
*/
@Override
protected void observeInstructionCount(Context cx, int instructionCount) {
SafeContext sctx = (SafeContext) cx;
//Check CPU Time
if (getMaxCpuTime() > 0) {
long currentTime = System.currentTimeMillis();
if (currentTime - sctx.getStartTime() > getMaxCpuTime()) {
throw new Error("Max CPU Time limit of " + getMaxCpuTime() + " was exceeded");
}
}
//Check Memory Consumption
if (getMaxMemory() > 0 && threadMonitor != null) {
if (sctx.getStartMemory() <= 0) {
sctx.setStartMemory(threadMonitor.getThreadAllocatedBytes(sctx.getThreadId()));
} else {
long currentAllocatedBytes = threadMonitor.getThreadAllocatedBytes(sctx.getThreadId());
if ((currentAllocatedBytes - sctx.getStartMemory()) >= getMaxMemory()) {
throw new Error("Max Memory limit of " + getMaxMemory() + " was exceeded");
}
}
}
}
実行時間と割り当てられたバイトを監視します。
ユーザーがループ (例: while(true) {} ) を作成しても、この関数は最終的に呼び出され、以前に定義された実行時間を超えた場合、エラーがスローされ、スクリプトの実行が停止します。
Janinoを使用してこの動作を再現しようとしていますが、スクリプトの実行を監視する同様のメカニズムがありません。ユーザーがブロッキング関数を呼び出した場合、スクリプトを実行しているスレッドで thread.stop() を突然呼び出す以外に、スクリプトを停止する方法がありません。これは問題になる可能性があります。(私が知る限り) thread.interrupt() のような他の呼び出しは、ブロッキング呼び出しを中断しません。
この問題を解決するにはどうすればよいですか?