Reputation: 393
I searchedon internet and learned other method of implementing it the problem now i have found out. my execution time always becomes more than that of time out if i write stdout=subprocess.PIPE in subprocess.Popen. If i am removing it then it is taking normal execution time
import subprocess, datetime, os, time, signal
//setting time for timeout
timeout=3
start = datetime.datetime.now()
process = subprocess.Popen(["python", "/home/bourne/untitled.py"],shell=False, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
while process.poll() is None:
time.sleep(0.1)
now = datetime.datetime.now()
if (now - start).seconds > timeout:
os.kill(process.pid, signal.SIGKILL)
os.waitpid(-1, os.WNOHANG)
print "error"
print (now - start).seconds
break
print (now - start).seconds
Upvotes: 2
Views: 3879
Reputation: 393
I have successfully solved the problem. the solution is
import subprocess, signal, os, threading, errno
from contextlib import contextmanager
class TimeoutThread(object):
def __init__(self, seconds):
self.seconds = seconds
self.cond = threading.Condition()
self.cancelled = False
self.thread = threading.Thread(target=self._wait)
def run(self):
"""Begin the timeout."""
self.thread.start()
def _wait(self):
with self.cond:
self.cond.wait(self.seconds)
if not self.cancelled:
self.timed_out()
def cancel(self):
"""Cancel the timeout, if it hasn't yet occured."""
with self.cond:
self.cancelled = True
self.cond.notify()
self.thread.join()
def timed_out(self):
"""The timeout has expired."""
raise NotImplementedError
class KillProcessThread(TimeoutThread):
def __init__(self, seconds, pid):
super(KillProcessThread, self).__init__(seconds)
self.pid = pid
def timed_out(self):
try:
os.kill(self.pid, signal.SIGKILL) // this is for linux you need to change it for windows
except OSError,e:
# If the process is already gone, ignore the error.
if e.errno not in (errno.EPERM, errno. ESRCH):
raise e
@contextmanager
def processTimeout(seconds, pid):
timeout = KillProcessThread(seconds, pid)
timeout.run()
try:
yield
finally:
timeout.cancel()
def example(cmd):
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
//setting the timeout to be 1 sec
with processTimeout(1, proc.pid):
stdout,stderr=proc.communicate()
resultcode = proc.wait()
if resultcode < 0:
#print "error: %i" % resultcode
return resultcode,0
else:
return stdout,stderr
//This is used to create new subprocess and it will return output as well as error
output,err=example(["python",filepath,"5"])
Upvotes: 1
Reputation: 1378
Thread can be handled in python VM, but process not. so u have to use OS api to kill ur process/subprocess, such as (in linux):
os.system("kill -9 %s"%(proc.pid))
and, using thread for timing is a bad idea. how about:
start_t = time.time()
TIME_END, TIME_SLEEP = 5, 1
while time.time() - start_t < TIME_END:
if proc.poll():
break
time.sleep(TIME_SLEEP)
Upvotes: 0
Reputation: 69082
You shouldn't spawn a new thread just for having it time out in 5 seconds and then use it's isAlive
status as break condition for a busy wait. You don't need an extra thread for that, you can messure the time in the first thread.
Instead of polling the thread as often as you can, you should use a delay (time.sleep
) to allow the processor to do some real work.
And you should know that if your process is generating a lot of output, it will block if you don't read it while the process is executing and let it fill up the pipe's buffer.
Upvotes: 3