CTRL_C_EVENT, отправленный дочернему процессу, убивает родительский процесс - PullRequest
0 голосов
/ 18 октября 2019

Я пишу скрипт, который запускает фоновый процесс параллельно. При перезапуске скрипта я хочу иметь возможность убить фоновый процесс и корректно завершить его, отправив ему сигнал CTRL_C_EVENT. По какой-то причине отправка сигнала CTRL_C_EVENT дочернему процессу также приводит к отправке того же сигнала родительскому процессу. Я подозреваю, что исключение KeyboardInterrupt не очищается после того, как дочерний процесс получает его, а затем перехватывает основной процесс.

Я использую Python версии 2.7.1 и работаю на 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, но она вызывается во второй раз, когда вызывается функция. Почему это происходит?

1 Ответ

0 голосов
/ 19 октября 2019

Я все еще ищу объяснение, почему возникает проблема, но я опубликую мой (хотя и несколько странный) обходной путь здесь на случай, если это поможет кому-то еще. Поскольку Ctrl + C распространяется на родительский процесс (все еще не совсем понятно, почему это происходит), я собираюсь просто перехватить исключение, когда оно прибывает, и ничего не делать.

Эрик предложил использовать дополнительный сторожевой поток для обработки завершения дополнительного процесса, но для моего приложения это создает дополнительную сложность и кажется немного излишним для того редкого случая, когда мне действительно нужно убить фоновый процесс. Большую часть времени фоновый процесс в моем приложении будет самопроизвольно закрываться, когда он будет завершен.

Я все еще открыт для предложений по лучшей реализации, которая не добавляет излишней сложности (больше процессов, потоков и т. Д.). .).

Модифицированный код здесь:

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...