Search code examples
javatimeoutonline-compilation

Time out a java code?


I am writing an online java programming app where I take a java code as input from user and returns the output after compilation and execution through a python script.

For controlling the memory heap I have a standard solution of using -Xms and -Xmx while running the code in JVM. I have installed Sun Java 1.7.0_40.

Now the problem is that I am confused about how to restrict the code with a time limit. For example any code submitted by user in my app should not run for more than T seconds, where T is a variable.

I wrote one simple hack using Timer class but the problem is I have to use a lot of regex to inject it in the user code which I primarily want to avoid. As I am more comfortable in python and c++ than java as a programmer, I need some guidance about whether there exists some easy solution for such problem or what are the pros and cons of using the Timer class.

Any help will be much appreciated! Thanks


Solution

  • I've done simple 'TimeoutThread' util using by ExecutorService.

    2 classes:

    package eu.wordnice.thread;
    /*** Runa.java ***/
    
    import java.util.concurrent.Callable;
    
    public class Runa implements Callable<Object> {
    
        private Runnable run = null;
    
        public Runa(Runnable run) {
            this.run = run;
        }
    
        public Runa(Thread run) {
            this.run = run;
        }
    
        public Runa() {}
    
        public Object call() throws Exception {
            if(run != null) {
                run.run();
            }
            return -1;
        };
    
    }
    

    And:

    package eu.wordnice.thread;
    /*** TimeoutThread.java ***/
    import java.util.Arrays;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;
    
    public class TimeoutThread {
    
        public Runa run = null;
        public ExecutorService executor = null;
        public long timeout = 100L;
        private boolean canceled = false;
        private boolean runed = false;
    
        public TimeoutThread(Runnable runit, long timeout) {
            this(new Runa(runit), timeout);
        }
    
        public TimeoutThread(Runa runit, long timeout) {
            this.run = runit;
            if(timeout < 1L) {
                timeout = 10L;
            }
            this.timeout = timeout;
        }
    
    
        public Object run() {
            return this.run(false);
        }
    
        public Object run(Object defaulte) {
    
            this.runed = true;
            List<Future<Object>> list = null;
            try {
                this.executor = Executors.newCachedThreadPool();
                list = executor.invokeAll(Arrays.asList(this.run), this.timeout, TimeUnit.MILLISECONDS);
            } catch (Exception e) {
                e.printStackTrace();
                this.canceled = true;
            }
            executor.shutdown();
    
            if(list == null) {
                return defaulte;
            }
            if(list.size() != 1) {
                return defaulte;
            }
    
            try {
                Future<Object> f = list.get(0);
                try {
                    return f.get();
                } catch (Exception e) {
                    this.canceled = true;
                }
            } catch (Exception e) { }
            return defaulte;
        }
    
        public boolean wasRunned() {
            return this.runed;
        }
    
        public boolean wasCanceled() {
            return this.canceled;
        }
    
    }
    

    Example:

    public static void main(String... blah) {
            TimeoutThread thr = new TimeoutThread(new Runa() {
    
                @Override
                public Object call() throws Exception {
                    while(true) {
                        System.out.println("Yeeee");
                        Thread.sleep(300L);
                    }
                }
    
    
    
            }, 500L);
            thr.run();
        }
    

    Print:

    Yeeee
    Yeeee
    

    EDIT!

    Sorry, that is Timeout Runnable. If you want Timeout Tread, just put the code / call into Thread.

    public static void main(String... blah) {
            final TimeoutThread thr = new TimeoutThread(new Runa() {
    
                @Override
                public Object call() throws Exception {
                    while(true) {
                        System.out.println("Yeeee");
                        Thread.sleep(300L);
                    }
                }
    
    
    
            }, 500L);
    
            new Thread() {
                @Override
                public void run() {
                    thr.run(); //Call it
                }
            }.start(); //Run it
        }