Signal (SIGTERM) not received by subprocess on Windows

丶灬走出姿态 提交于 2019-12-02 00:18:20

问题


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.

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())

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

EDIT: 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...


回答1:


As you are using Windows, SIGTERM handler is useless, more reference:

On Windows, the C runtime implements the six signals that are required by standard C: SIGINT, SIGABRT, SIGTERM, SIGSEGV, SIGILL, and SIGFPE.

SIGABRT and SIGTERM are implemented just for the current process.

But you could use signal.CTRL_BREAK_EVENT as an alternative.

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


来源:https://stackoverflow.com/questions/47306805/signal-sigterm-not-received-by-subprocess-on-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!