I want to run subprocesses with limits on the execution time and the
output size of the subprocess. If the subprocess exceeds limits, then
the parent should kill it gracefully (SIGTERM rather than SIGKILL). This
is a useful safety mechanism if you have a CGI interface that starts
jobs per user request.
As a result of this effort, I have a comment and a question:
(1) I don't think that process control is thought through very well
in Python. Do I really need os, popen2, fcntl, signal, and select?
If so, it is not nearly as attractive as, for example, using the cgi
module to process cgi input.
(2) I still don't know if I am doing this right. I didn't completely
understand the recent discussion about the os.kill() function, and in
general I am not sure if what I have is safe. Is it okay?
-----------------------------------
import os,sys,time,pop en2,fcntl,signa l,select,except ions
class ProcError(excep tions.Exception ):
def __init__(me,typ e):
if type == 'space': me.args = 'Space limit exceeded!'
elif type == 'time': me.args = 'Time limit exceeded!'
else: me.args = 'Unknown error'
def subprocess(comm and,timeout=Non e,spaceout=None ):
proc = popen2.Popen4(c ommand)
pout = proc.fromchild
proc.tochild.cl ose()
output = ''
try:
if timeout:
fcntl.fcntl(pou t,fcntl.F_SETFL ,os.O_NONBLOCK)
endtime = time.time() + timeout
while 1:
timeleft = endtime - time.time()
if timeleft <= 0: raise ProcError,'time '
(ready,toss,tos s) = select.select([pout],[],[],timeleft)
if not ready: raise ProcError,'time '
if spaceout:
output += pout.read(space out-len(output))
if len(output) >= spaceout: raise ProcError,'spac e'
else:
output += pout.read()
if proc.poll() >= 0: break
else:
if spaceout: output = pout.read(space out)
else: output = pout.read()
if proc.poll(): raise ProcError,'spac e'
except ProcError:
print sys.exc_value # Debug
os.kill(proc.pi d,signal.SIGTER M)
return output
--
/\ Greg Kuperberg (UC Davis)
/ \
\ / Visit the Math ArXiv Front at http://front.math.ucdavis.edu/
\/ * All the math that's fit to e-print *