Обработчик python SIGTERM не вызывается в многопроцессорной обработке

Я воспроизвел следующий фрагмент, чтобы воспроизвести проблему, с которой я столкнулся при работе с обработчиком SIGTERM:

  1. основной процесс с обработчиком SIGTERM.

  2. поток, порожденный основным процессом

  3. подпроцесс, порожденный вышеприведенным потоком

Цель состоит в том, чтобы понять работу обработчика SIGTERM. Я предполагаю, что обработчик SIGTERM будет унаследован как порожденным потоком, так и процессом. Есть раздел, где происходит взаимоблокировка (из-за того, что общая очередь не читается). Это поддерживает все процессы и потоки в живых, так как существует взаимоблокировка.

from multiprocessing import Process, Queue
from threading import Thread
import os
import sys
import signal


def sigtermHandlerNew():
    print "SIGTERM received for process: {}".format(os.getpid())
    sys.exit()


def f(q):
    print "f proc id: {}".format(os.getpid())
    q.put('X' * 1000000)


def proc_starter():
    queue = Queue()
    p = Process(target=f, args=(queue,))
    p.start()
    p.join()  # this deadlocks
    obj = queue.get()


def main():
    signal.signal(signal.SIGTERM, sigtermHandlerNew)
    print "main process id: {}".format(os.getpid())
    t = Thread(target=proc_starter)
    t.start()
    t.join()


main()

После запуска этой программы у меня будут запущены 2 процесса. Я наблюдаю здесь странное поведение - когда я пытаюсь убить любой из процессов с помощью SIGTERM($ kill -15 <proc-id>), я вижу, что функция для обработчика SIGTERM не вызывается, и этот тупик остается навсегда (пока я не сигнализирую SIGKILL)

Может ли кто-нибудь помочь мне понять, почему сигнал не соблюдается процессом? Вы можете напрямую запустить этот фрагмент.


person Barun Sharma    schedule 19.12.2018    source источник


Ответы (1)


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

Более подробно, на вас влияет тот факт, что в Python 2 некоторые примитивы, использующие базовые блокировки, не могут быть прерваны сигналами проблема.

Эта проблема больше не затрагивает Python 3, поэтому я настоятельно рекомендую вам перейти на более новую версию интерпретатора.

Если вы не можете поступить иначе, обходной путь — установить тайм-ауты для блокирующих операций, таких как Queue.get.

person noxdafox    schedule 19.12.2018
comment
Спасибо за Ваш ответ. Хотя я не могу сразу переключиться на Python3, этот ответ помогает мне подумать о других альтернативах. На данный момент проблема не устранена, и мне, возможно, придется подумать об альтернативах. Спасибо. - person Barun Sharma; 26.12.2018