我有一个服务器,启动一个subprocess,我可以设法做一个send_signal(SIGTERM)
这将杀死进程。 但不够优雅。 如果我从shell调用我的subprocess(即作为一个进程),定义的信号处理程序将踢入并正常退出。
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
跟踪Terminate signal received
并closures应用程序。 但是,当app.py由服务器启动,我打电话exit_app
服务器中的exit_app
,我得到一个跟踪Subprocess is alive
(从server.py),应用程序被杀害,但信号不捕获应用程序的signalhandler exit_signal_handler
编辑:看来send_signal()
不会发送信号到subprocess捕获信号的意义上。 它发送了一个信号在子过程中发生的行为:
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))
这可能回答我的问题,但我会打开它…
正如你使用Windows, SIGTERM
处理程序是无用的 ,更多的参考 :
在Windows上,C运行库实现了标准C:SIGINT,SIGABRT,SIGTERM,SIGSEGV,SIGILL和SIGFPE所需的六个信号。
SIGABRT和SIGTERM仅适用于当前进程。
但是,您可以使用signal.CTRL_BREAK_EVENT
作为替代 。
即在app.py中创建一个处理SIGBREAK的信号处理程序,但是从父级发送CTRL_BREAK_EVENT
。 另外,确保使用creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
启动你的子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