我有一个启动子进程的服务器,我可以设法执行一个send_signal(SIGTERM)
来杀死进程。但不是优雅的。
如果我从shell调用我的子进程(即作为单个进程),定义的信号处理程序将启动并正常退出。
server.py:
(所以......我从另一个脚本中首先调用start_app()
,然后调用exit_app()
def start_app():
app = subprocess.Popen("python app.py")
def exit_app():
p = app.poll()
if p==None:
print("Subprocess is alive") # debug
app.send_signal(signal.SIGTERM)
app.py
def exit_signal_handler(signal, frame):
print("Terminate signal received")
app.exit()
if __name__ == '__main__':
app = QApplication(sys.argv)
signal.signal(signal.SIGTERM, exit_signal_handler)
signal.signal(signal.SIGINT, exit_signal_handler)
sys.exit(app.exec())
同样,如果我从shell调用app.py并发送SIGTERM
信号,我会得到跟踪Terminate signal received
并关闭应用。
但是当app.py由服务器启动并且我在服务器中调用exit_app
时,我得到一个跟踪Subprocess is alive
(来自server.py)并且app被杀死但是信号没有在应用程序中被捕获。 s signalhandler exit_signal_handler
编辑:
在子进程捕获信号的意义上,send_signal()
似乎没有向子进程发送信号 。它发送一个信号,用于在子进程上执行操作:
def send_signal(self, sig):
"""Send a signal to the process
"""
if sig == signal.SIGTERM:
self.terminate()
elif sig == signal.CTRL_C_EVENT:
os.kill(self.pid, signal.CTRL_C_EVENT)
elif sig == signal.CTRL_BREAK_EVENT:
os.kill(self.pid, signal.CTRL_BREAK_EVENT)
else:
raise ValueError("Unsupported signal: {}".format(sig))
这可能回答了我的问题,但我会把它打开......
答案 0 :(得分:3)
当您使用Windows时,SIGTERM
处理程序为useless,更多reference:
在Windows上,C运行时实现标准C所需的六个信号:SIGINT,SIGABRT,SIGTERM,SIGSEGV,SIGILL和SIGFPE。
SIGABRT和SIGTERM仅针对当前流程实施。
但您可以将signal.CTRL_BREAK_EVENT
用作alternative。
即。在app.py中创建一个处理SIGBREAK
的信号处理程序,但从父项发送CTRL_BREAK_EVENT
。另外,确保使用creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
启动子进程(否则它也将终止父进程)
app = subprocess.Popen("python app.py", shell=True, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
time.sleep(1)
while 1:
p = app.poll()
if p is not None:
break
app.send_signal(signal.CTRL_BREAK_EVENT)
time.sleep(2)
app.py:
exit = False
def exit_signal_handler(signal, frame):
global exit
print("Terminate signal received")
exit = True
signal.signal(signal.SIGBREAK, exit_signal_handler)
while not exit:
pass