Многопроцессорные подпроцессы произвольно получают SIGTERM - PullRequest
0 голосов
/ 03 декабря 2018

Я возлюсь с multiprocessing и signal.Я создаю пул, и пусть рабочие ловят SIGTERM с.Без видимых причин я наблюдаю, что подпроцессы случайным образом получают SIGTERM с.Вот MWE:

import multiprocessing as mp
import signal
import os
import time

def start_process():
    print("Starting process #{}".format(os.getpid()))

def sigterm_handler(signo, _frame):
    print("Process #{} received a SIGTERM".format(os.getpid()))

def worker(i):
    time.sleep(1)

signal.signal(signal.SIGTERM, sigterm_handler)
while True:
    with mp.Pool(initializer=start_process) as pool:
        pool.map(worker, range(10))
    time.sleep(2)

Вывод:

Starting process #7735
Starting process #7736
Starting process #7737
Starting process #7738
Starting process #7739
Starting process #7740
Starting process #7741
Starting process #7742
Job done.
Starting process #7746
Starting process #7747
Starting process #7748
Starting process #7749
Starting process #7750
Starting process #7751
Starting process #7752
Starting process #7753
Process #7748 received a SIGTERM
Process #7746 received a SIGTERM
Job done.
Starting process #7757
Starting process #7758
Starting process #7759
Starting process #7760
Starting process #7761
Starting process #7762
Starting process #7763
Starting process #7764

Как видите, это выглядит непредсказуемо.

Итак, откуда эти SIGTERM сот?Это нормально?Я гарантированно, что рабочие закончат свою работу?И в конце концов, нормально ли иметь подпроцессы захвата SIGTERM s?

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Это нормально и может произойти, когда ваш пул выполняет __exit__ после выхода из контекстного менеджера.Поскольку рабочие уже закончили свою работу, беспокоиться не о чем.Сам пул вызывает SIGTERM для работников, у которых нет кода выхода, когда пул проверяет его.Это срабатывает в Pool._terminate_pool -методе (Python 3.7.1):

    # Terminate workers which haven't already finished.
    if pool and hasattr(pool[0], 'terminate'):
        util.debug('terminating workers')
        for p in pool:
            if p.exitcode is None:
                p.terminate()

Работники пула объединятся несколькими строками позже:

    if pool and hasattr(pool[0], 'terminate'):
        util.debug('joining pool workers')
        for p in pool:
            if p.is_alive():
                # worker has not yet exited
                util.debug('cleaning up worker %d' % p.pid)
                p.join()

В сценариикогда вы будете явно вызывать pool.terminate(), пока ваши работники еще работают (например, вы используете pool.map_async, а затем используете pool.terminate()), ваше приложение заблокирует ожидание на p.join() (если вы в конечном итоге не разрешите своему sigterm_handlerзвоните sys.exit()).

Лучше не связывайтесь с обработчиками сигналов, если вам не нужно.

0 голосов
/ 03 декабря 2018

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

mp.log_to_stderr(logging.DEBUG)

и изменить start_process ():

def start_process():
    proc= mp.current_process()
    print("Starting process #{}, its name is {}".format(os.getpid(),proc.name))
...