Windows 上的子进程未收到信号 (SIGTERM) [英] Signal (SIGTERM) not received by subprocess on Windows

查看:60
本文介绍了Windows 上的子进程未收到信号 (SIGTERM)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个启动子进程的服务器,我可以设法执行一个 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 SIGTERMsignal 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆