python: поймать SIGINT в процессе чтения данных из сокета

У меня есть скрипт Python, который я хотел бы остановить, отправив сигнал «SIGINT» с помощью командной строки:

kill -2 <PID>

Сценарий порождает дочерний процесс, а затем входит в бесконечный цикл, в котором он пытается получить данные из сокета. Я установил обработчик сигнала, но похоже, что моя программа не ловит сигнал. Вот мой код:

import signal
import multiprocessing

def newBreakHandler(signum, frame):
    global progBreak
    progBreak = True


def runMain():

    client = multiprocessing.Client(<address>)
    # ......

    # Insert break handler
    signal.signal(signal.SIGINT, newBreakHandler)


    while not progBreak:
        try:
            # Some other stuff...
            # ...
            childProc = multiprocessing.Process(target=childProcName)                                                                                                                          
            childProc.start()


            # Main loop
            while not progBreak:
                command = client.recv_bytes()
        except:
            pass

    print "Exiting..."

Проблема в том, что всякий раз, когда я отправляю:

kill -2 <PID>

Я никогда не вижу напечатанного текста «Выход», а PID не убит. Я думаю, это потому, что внутренний цикл "пока" занят ожиданием новых данных от клиента, но если клиент не отправляет новые данные.

Есть ли способ решить проблему?

ТИА!!!


person toti08    schedule 11.07.2017    source источник
comment
Разве while not procBreak: ... не блокирует внешний цикл?   -  person bakatrouble    schedule 11.07.2017
comment
Отредактируйте сообщение, чтобы оно было минимальным, полным и поддающимся проверке.   -  person klutt    schedule 11.07.2017
comment
Хорошо, я попытаюсь сделать простой пример, упрощающий мою ситуацию.   -  person toti08    schedule 11.07.2017


Ответы (1)


Похоже, ваш внутренний цикл блокирует проверку progBreak, у меня работает этот код:

import signal

progBreak = False

def newBreakHandler(signum, frame):
    global progBreak
    progBreak = True


def runMain():
    global progBreak

    signal.signal(signal.SIGINT, newBreakHandler)


    while not progBreak:
        while not progBreak and client.poll():
            command = client.recv_bytes()

    print "Exiting..."

runMain()
person bakatrouble    schedule 11.07.2017
comment
Дело в том, что этот простой код работает, даже если вы поместите в него внутренний цикл, поэтому я предполагаю, что в программе что-то еще не так. Я обновлю вопрос, чтобы сделать его более конкретным, спасибо! - person toti08; 11.07.2017
comment
Я изменил свой вопрос, проблема в том, что я делаю внутри внутреннего цикла while... - person toti08; 11.07.2017
comment
Пока procBreak не становится истинным (внутренний цикл не останавливается), условие внешнего цикла не проверяется, поэтому интерпретатор должен сначала выйти из внутреннего цикла, чтобы увидеть, что внешний цикл также должен быть остановлен. - person bakatrouble; 11.07.2017
comment
Попробуйте также добавить progBreak проверку во внутренний цикл (while not procBreak and not progBreak) - person bakatrouble; 11.07.2017
comment
Тогда строка command = client.recv_bytes() блокирует выполнение, боюсь, вы ничего не можете с этим поделать. - person bakatrouble; 11.07.2017
comment
Затем проверьте multiprocessing.Connection.poll(), это позволяет проверить, есть ли какие-либо данные для получения, поэтому recv_bytes() не блокирует выполнение, ожидая ничего (добавлен пример для ответа). - person bakatrouble; 11.07.2017
comment
Да, я думаю, вы правы, я также проверял документацию. Спасибо! - person toti08; 11.07.2017
comment
Если вы измените свой ответ этим последним комментарием, я могу его принять. - person toti08; 11.07.2017