Here's how I do it ... it does use subprocess so you'll need to tweak it to use popen.
class KillerThread(threading.Thread):
def __init__(self, pid, timeout, event ):
threading.Thread.__init__(self)
self.pid = pid
self.timeout = timeout
self.event = event
self.setDaemon(True)
def run(self):
self.event.wait(self.timeout)
if not self.event.isSet() :
try:
os.kill( self.pid, signal.SIGKILL )
except OSError, e:
#This is raised if the process has already completed
pass
def runTimed(dt, args, kwargs ):
event = threading.Event()
proc = subprocess.Popen(args, **kwargs )
killer = KillerThread(proc.pid, dt, event)
killer.start()
(stdout, stderr) = proc.communicate()
event.set()
return (stdout,stderr, proc.returncode)
#EXAMPLE USAGE - lets it run for at most 3 seconds
(stdout, stderr, returncode) = \
runTimed(3, \
["path/to/my/executable", "arg1" ] , \
{'stdout':subprocess.PIPE, 'stderr':subprocess.PIPE} )
You can probably avoid the need for an additional thread if you use stderr, stdout
directly rather than using communicate, you'd just need to be careful to use non-blocking IO on those handles.