JeremyKun
JeremyKun

Reputation: 3002

Sandbox shell programs on time

I'm writing a grading robot for a Python programming class, and the students' submissions may loop infinitely. I want to sandbox a shell call to their program so that it can't run longer than a specific amount of time. I'd like to run, say,

restrict --msec=100 --default=-1 python -c "while True: pass"

and have it return -1 if the program runs longer than 100ms, and otherwise return the value of the executed expression (in this case, the output of the python program)

Does Python support this internally? I'm also writing the grading robot in Perl, so I could use some Perl module wrapped around the call to the shell script.

Upvotes: 2

Views: 587

Answers (2)

unutbu
unutbu

Reputation: 879859

Use apply_async to call the student's function, (foo in the example below). Use the get method with a timeout to get the result if it returns in 0.1 seconds or less, otherwise get raise a TimeoutError:

import multiprocessing as mp
import time
import sys

def foo(x):
    time.sleep(x)
    return x*x

pool = mp.Pool(1)

for x in (0.01, 1.0):
    try:
        result = pool.apply_async(foo, args = (x,)).get(timeout = 0.1)
    except KeyboardInterrupt:
        pool.terminate()
        sys.exit("Cancelled")
    except mp.TimeoutError:
        print('Timed out')
    else:
        print "Result: {r}".format(r = result)

Or, if the student submits a script instead of function, then you could use jcollado's Command class.

Upvotes: 3

S.Lott
S.Lott

Reputation: 391872

The standard approach is to do the following.

  1. Create a subprocess which runs the student's program in it's own Python instance.

  2. Wait for a time.

  3. If the student subprocess exits, good.

  4. If the subprocess has not exited, you need to kill it.

You'll be happiest downloading the psutil module which allows each status checking of the subprocess.

Upvotes: 0

Related Questions