CTRL_C_EVENT 发送到子进程杀死父进程 [英] CTRL_C_EVENT sent to child process kills parent process

查看:40
本文介绍了CTRL_C_EVENT 发送到子进程杀死父进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个并行运行后台进程的脚本.重新启动脚本时,我希望能够通过向它发送 CTRL_C_EVENT 信号来终止后台进程并干净地退出它.但出于某种原因,将 CTRL_C_EVENT 信号发送到子进程也会导致相同的信号发送到父进程.我怀疑 KeyboardInterrupt 异常在子进程获取并被主进程捕获后没有被清除.

I'm writing a script that runs a background process in parallel. When restarting the script I want to be able to kill the background process and exit it cleanly by sending it a CTRL_C_EVENT signal. For some reason though, sending the CTRL_C_EVENT signal to the child process also causes the same signal to be sent to the parent process. I suspect that the KeyboardInterrupt exception isn't being cleaned up after the child process gets it and is then caught by the main process.

我使用的是 Python 2.7.1 版并在 Windows Server 2012 上运行.

I'm using Python version 2.7.1 and running on Windows Server 2012.

import multiprocessing
import time
import signal
import os

def backgroundProcess():
    try:
        while(True):
            time.sleep(10)

    except KeyboardInterrupt:
        #exit cleanly
        return


def script():
    try:
        print "Starting function"

        #Kill all background processes
        for proc in multiprocessing.active_children():
            print "Killing " + str(proc) + " with PID " + str(proc.pid)
            os.kill(proc.pid, signal.CTRL_C_EVENT)

        print "Creating background process"
        newProc = multiprocessing.Process(target=backgroundProcess)
        print "Starting new background process"
        newProc.start()
        print "Process PID is " + str(newProc.pid)

    except KeyboardInterrupt:
        print "Unexpected keyboard interrupt"

def main():
    script()
    time.sleep(5)
    script()

我希望 script() 函数永远不会收到 KeyboardInterrupt 异常,但它会在第二次调用该函数时触发.为什么会发生这种情况?

I expect that the script() function should never be receiving a KeyboardInterrupt exception, but it is triggered the second time that the function is called. Why is this happening?

推荐答案

我仍在寻找有关问题发生原因的解释,但我会在此处发布我的(尽管有些 hacky)解决方法,以防它对任何人有所帮助别的.由于 Ctrl+C 被传播到父进程(仍然不完全确定为什么会发生这种情况),我将在它到达时捕获异常并且什么都不做.

I'm still looking for an explanation as to why the issue occurs, but I'll post my (albeit somewhat hacky) workaround here in case it helps anyone else. Since the Ctrl+C gets propagated to the parent process (still not entirely sure why this happens), I'm going to just catch the exception when it arrives and do nothing.

Eryk 建议使用额外的看门狗线程来处理终止额外的进程,但对于我的应用程序来说,这会引入额外的复杂性,而且对于我实际上需要终止后台进程的罕见情况来说似乎有点过头了.大多数情况下,我的应用程序中的后台进程会在完成后自行关闭.

Eryk suggested using an extra watchdog thread to handle terminating the extra process, but for my application this introduces extra complexity and seems a bit overkill for the rare case that I actually need to kill the background process. Most of the time the background process in my application will close itself cleanly when it's done.

我仍然乐于接受不会增加太多复杂性(更多进程、线程等)的更好实现的建议.

I'm still open to suggestions for a better implementation that doesn't add too much complexity (more processes, threads, etc.).

此处修改代码:

import multiprocessing
import time
import signal
import os

def backgroundProcess():
    try:
        while(True):
            time.sleep(10)

    except KeyboardInterrupt:
        #Exit cleanly
        return


def script():
    print "Starting function"

    #Kill all background processes
    for proc in multiprocessing.active_children():
        print "Killing " + str(proc) + " with PID " + str(proc.pid)
        try:
            #Apparently sending a CTRL-C to the child also sends it to the parent??
            os.kill(proc.pid, signal.CTRL_C_EVENT)
            #Sleep until the parent receives the KeyboardInterrupt, then ignore it
            time.sleep(1)
        except KeyboardInterrupt:
            pass

    print "Creating background process"
    newProc = multiprocessing.Process(target=backgroundProcess)
    print "Starting new background process"
    newProc.start()
    print "Process PID is " + str(newProc.pid)

def main():
    script()
    time.sleep(5)
    script()

这篇关于CTRL_C_EVENT 发送到子进程杀死父进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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