超时时杀死或终止子进程?
我想尽可能快地重复执行一个子进程。但是,有时这个过程需要很长时间,所以我想杀死它。 我用signal.signal(...)象下面这样:超时时杀死或终止子进程?
ppid=pipeexe.pid
signal.signal(signal.SIGALRM, stop_handler)
signal.alarm(1)
.....
def stop_handler(signal, frame):
print 'Stop test'+testdir+'for time out'
if(pipeexe.poll()==None and hasattr(signal, "SIGKILL")):
os.kill(ppid, signal.SIGKILL)
return False
但有时这些代码会试图停止执行下一轮。 停止测试/ home/lu/workspace/152/treefit/test2超时 /bin/sh:/ home/lu/workspace/153/squib_driver:找不到---这是下一次执行;该程序错误地停止它。
有谁知道如何解决这个问题?我想在时间停止不执行1秒的时间。睡眠(n)经常等待n秒。我不希望我希望它可以执行少于1秒
你可以做这样的事情:
import subprocess as sub
import threading
class RunCmd(threading.Thread):
def __init__(self, cmd, timeout):
threading.Thread.__init__(self)
self.cmd = cmd
self.timeout = timeout
def run(self):
self.p = sub.Popen(self.cmd)
self.p.wait()
def Run(self):
self.start()
self.join(self.timeout)
if self.is_alive():
self.p.terminate() #use self.p.kill() if process needs a kill -9
self.join()
RunCmd(["./someProg", "arg1"], 60).Run()
的想法是,你创建一个运行命令一个线程,并杀死它,如果超时超过某个合适的值,在这种情况下60秒。
我想这是面向事件编程中使用线程和进程的常见同步问题。
如果您应始终只有一个子进程在运行,请确保当前子进程在运行下一个子进程之前被终止。否则,信号处理程序可能会获得对最后一个子进程运行的引用,并忽略较早的子进程。
假设子流程A正在运行。在报警信号处理之前,子过程B启动。紧接着,你的报警信号处理程序试图杀死一个子进程。由于当前PID(或当前子流程管道对象)在启动子进程时被设置为B,因此B被杀死并且A继续运行。
我的猜测是否正确?
为了让您的代码更易于理解,我将包含在杀死当前子进程的部分之后创建新子进程的部分。这将清楚表明只有一个子进程在任何时间运行。信号处理程序可以执行子进程查杀和启动,就好像它是循环运行的迭代块一样,在这种情况下,每隔1秒用事件驱动报警信号。
这是我写的一个子进程执行的看门狗。我用它现在很多,但我不这么有经验,所以也许有一些缺陷在里面:
import subprocess
import time
def subprocess_execute(command, time_out=60):
"""executing the command with a watchdog"""
# launching the command
c = subprocess.Popen(command)
# now waiting for the command to complete
t = 0
while t < time_out and c.poll() is None:
time.sleep(1) # (comment 1)
t += 1
# there are two possibilities for the while to have stopped:
if c.poll() is None:
# in the case the process did not complete, we kill it
c.terminate()
# and fill the return code with some error value
returncode = -1 # (comment 2)
else:
# in the case the process completed normally
returncode = c.poll()
return returncode
用法:
return = subprocess_execute(['java', '-jar', 'some.jar'])
评论:
- 在这里,看门狗超时在几秒钟内;但通过更改
time.sleep()
值可以轻松更改为任何需要的值。time_out
必须相应记录; - 根据需要,这里可能更适合提出一些例外。
文档:我努力了一下subprocess
模块的文档,明白subprocess.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, dir, args, kwargs):
event = threading.Event()
cwd = os.getcwd()
os.chdir(dir)
proc = subprocess.Popen(args, **kwargs)
os.chdir(cwd)
killer = KillerThread(proc.pid, dt, event)
killer.start()
(stdout, stderr) = proc.communicate()
event.set()
return (stdout,stderr, proc.returncode)
所以基本上如果子进程运行超过1秒,你想杀了它并开始下一个?它是否正确? – 2010-11-11 20:06:28
你如何创建你的子过程?因为它看起来像表达式__ pid = pipeexe.pid__正在获取将要运行的下一个子进程! – mouad 2010-11-11 21:03:33
所以基本上如果子进程运行超过1秒,你想杀了它并开始下一个?它是否正确?是的,这是正确的 – user504909 2010-11-11 23:31:53