1

I'm trying to build a scripting sandbox using Janino so that I can safely execute user functions by limiting the imports, CPU time and allocated bytes.

In Rhino (for javascript code) I have a function available named observeInstructionCount(Context ctx, int instructionCount) that is called every X instructions where X can be defined by the user when building the environment.

In this function I can do something like this:

/**
 * 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");

            }
        }
    }
}

to monitor the execution time and allocated bytes.

Even if the user creates a loop (e.g. while(true) {} ) this function will eventually be called and if the perviously defined execution time was exceeded it will throw an error and the script execution will stop.

I'm trying to replicate this behaviour using Janino but I don't have a similar mechanism to monitor the scripts execution. If a user calls a blocking function I have no way to stop the script other then to abruptly call thread.stop() on the thread that is executing the script, which can be problematic. Any other calls like thread.interrupt() (as far as I know) won't interrupt blocking calls.

Any Ideas on how can I solve this problem?

Pedro Chaves
  • 123
  • 13
  • I think abruptly stopping the thread is acceptable in this case. You're saying that the user code has spent an unacceptable amount of time running, so why should you care to (spend more time and) gracefully stop it? – Jonathon Reinhart Nov 13 '17 at 10:51
  • @JonathonReinhart The script take as parameters objects that may be latter used by other threads and I don't want to leave these objects in an inconsistent state. – Pedro Chaves Nov 13 '17 at 11:05

0 Answers0