I want to sandbox an application where end users can submit Java code to a server where it is compiled and executed (kind of a web-based IDE as part of an educational game). Most aspects can easily be handled by using either the standard security manager or verification of used APIs against a whitelist using ASM or similar.
An open problem is how to deal with infinite loops. As threads have their own stack, StackOverFlowErrors seem to be thread-local. I have done a little spike and came up with this:
public class TryToSurviveAStackOverflow {
public static void main(String[] args) throws Exception {
final Runnable infiniteLoop = new Runnable() {
@Override public void run() {
run();
}
};
Runnable sandboxed = new Runnable() {
@Override public void run() {
try {
Thread.sleep(10000); // some time to connect VisualVM to monitor this
infiniteLoop.run();
}
catch (StackOverflowError x) {
System.err.println("Thread crashed with stack overflow");
} catch (InterruptedException e) {
System.err.println("Thread interruped");
}
}
};
Thread thread = new Thread(sandboxed,"infinite loop");
thread.start();
thread.join();
System.out.println(thread.getState());
System.out.println("I am still alive");
}
}
This seems to work, but how safe is this? In particular, what happens to the stack space used by the unsafe thread? I can see that the state of the thread is set to TERMINATED.
Any help / pointers are highly appreciated !
Cheers, Jens