Windows 上的子进程未收到信号 (SIGTERM) [英] Signal (SIGTERM) not received by subprocess on Windows
问题描述
我有一个启动子进程的服务器,我可以设法执行一个 send_signal(SIGTERM)
来终止进程.但并不优雅.如果我从 shell 调用我的子进程(即作为单个进程),则定义的信号处理程序将正常启动并退出.
I have a server that starts a subprocess, and I can manage to do a send_signal(SIGTERM)
which will kill the process. But not gracefully.
If I call my subprocess from shell (i.e. as a single process), the defined signal handler will kick in and exit gracefully.
服务器.py:(所以...从另一个脚本我首先调用 start_app()
,然后是 exit_app()
server.py:
(so.. from another script I first call start_app()
, and later 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 信号接收
并且应用程序关闭.但是当 app.py 由服务器启动并且我在服务器中调用 exit_app
时,我得到一个跟踪 Subprocess is alive
(来自 server.py)并且应用程序被杀死但信号未被应用程序的信号处理程序exit_signal_handler
Again, if I call app.py from shell and send a SIGTERM
signal I get a trace Terminate signal received
and app closes.
But when app.py is started by server and I call exit_app
in server, I get a trace Subprocess is alive
(from server.py) and app is killed but the signal is not caught in app's signalhandler exit_signal_handler
在子进程捕获信号的意义上,似乎 send_signal()
没有向子进程发送信号到.它发送一个信号,让子进程发生一个动作:
It seems send_signal()
doesn't send a signal to the subprocess in the sense that subprocess catches the signal. It send`s a signal for an action to take place on the 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))
这可能回答了我的问题,但我会保持开放...
This probably answers my question but I'll leave it open...
推荐答案
当您使用 Windows 时,SIGTERM
处理程序是 没用,更多参考:
As you are using Windows, SIGTERM
handler is useless, more reference:
在 Windows 上,C 运行时实现标准 C 所需的六个信号:SIGINT、SIGABRT、SIGTERM、SIGSEGV、SIGILL 和 SIGFPE.
On Windows, the C runtime implements the six signals that are required by standard C: SIGINT, SIGABRT, SIGTERM, SIGSEGV, SIGILL, and SIGFPE.
SIGABRT 和 SIGTERM 仅针对当前进程实现.
SIGABRT and SIGTERM are implemented just for the current process.
但您可以使用 signal.CTRL_BREAK_EVENT
作为 替代.
But you could use signal.CTRL_BREAK_EVENT
as an alternative.
即在 app.py 中创建一个处理 SIGBREAK
的信号处理程序,但从父级发送 CTRL_BREAK_EVENT
.另外,请确保使用 creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
启动您的子进程(否则它也会杀死父进程)
I.e. create a signal handler in app.py that handles SIGBREAK
, but send the CTRL_BREAK_EVENT
from the parent. Also, make sure to start your subprocess using creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
(otherwise it will kill the parent as well)
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
这篇关于Windows 上的子进程未收到信号 (SIGTERM)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!