2014-10-07 2 views
1

У меня есть питон приложение, в котором я создаю несколько новых экземпляров объекта multiprocessing.Process от основного процесса в моде аналогично:Каков правильный способ регистрации обработчиков сигналов в Python?

self.my_proc = Process(name='foo', target=self.bar, args=(self.some_var,)) 
    self.my_proc.daemon = True 
    self.my_proc.start() 
    ... 

    @staticmethod 
    def bar(some_var): 
     while True: 
      do stuff forever 

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

Я действительно хочу, чтобы основной (родительский) процесс получил обратный вызов обработчика сигнала, потому что это процесс, который очистит все подпроцессы. Поэтому моя программа работает так, как мне нужно. Но я обеспокоен тем, что есть лучший (правильный?) Способ обработки сигналов в многопроцессных приложениях Python. Здесь?

ответ

1

В этом нет ничего делать с Python как таковым. Он отражает реализацию сигналов UNIX (Linux) и их поведение, когда процесс создает дочерние процессы (с использованием системного вызова fork). Вот цитата из руководства, которое объясняет поведение, вы заметили:

Ребенок, созданный через fork(2) наследует копию сигнала диспозиции своего родителя.
Во время execve(2), расположение обработанных сигналов сбрасывается до значения по умолчанию; Расположения игнорируемых сигналов остаются без изменений.

+0

Я считаю, что POSIX 'fork' фактически не документирует, что происходит с обработчиками сигналов; допустимо скопировать их, сбросить их до значений по умолчанию или почти что угодно. Конечно, вы не можете переносить все, что не является безопасным для асинхронного сигнала между 'fork' и' exec', так что это не имеет особого значения для переносимого кода ... – abarnert

+0

Кроме того, стоит отметить, что последнее 3.x дает вы, по крайней мере, можете больше контролировать это, чего нет в 2.x: вы можете «дочерние процессы fork + exec» вместо «fork», и вы можете сделать «fork from the thread» плюс 'pthread_sigmask' что некоторые веб-серверы используют на некоторых платформах * nix. – abarnert

+0

@abarnert Я всегда получаю дополнительное чтение после ваших комментариев :) Не то, чтобы я жаловался. – isedev

0

Если это удобно в основной процесс (как это кажется), и если вы заботитесь только о ловле SIGINT, я предпочитаю, чтобы поймать KeyboardInterrupt, а не установка обработчика сигнала:

@staticmethod 
def bar(): 
    try: 
     while True: 
      # do stuff forever 
      pass 
    except KeyboardInterrupt: 
     # Tell subprocesses to shutdown gracefully 
     pass 
Смежные вопросы