Многопроцессорный пул Python изменяет стек при использовании `maxtasksperchild` - PullRequest
0 голосов
/ 24 мая 2019

Я пишу функцию в Python 3.7, которая обрабатывает исключения в многопроцессорной установке путем проверки стека вызовов.

Однако я заметил, что если я укажу опцию maxtasksperchild с объектом multiprocessing.Pool, некоторые процессы (предположительно, созданные после того, как были убиты первые) возвращают совершенно другую трассировку стека, которая не даже пройти по вызывающей функции.

Минимальный воспроизводимый пример:

#!/usr/bin/env python3

import inspect

from multiprocessing import Pool

def mp_caller():
    with Pool() as pool:
        pool.map(_bork, range(10))
        pool.close()
        pool.join()

def mp_caller_kill():
    with Pool(maxtasksperchild=1) as pool:
        pool.map(_bork, range(10))
        pool.close()
        pool.join()

def _bork(i):
    try:
        if i % 3 == 0:
            raise RuntimeError("BLAH")
        print(i)
    except:
        handle_exception()

def handle_exception():
    print("Stack info: {}".format(
        [
            f.function
            for f in inspect.getouterframes(inspect.currentframe())
        ]
    ))

if __name__ == "__main__":
    print("Without killing processes:")
    mp_caller()
    print("Killing processes:")
    mp_caller_kill()

Выход:

Without killing processes:
2
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller', '<module>']
4
5
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller', '<module>']
7
8
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller', '<module>']
1
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller', '<module>']
Killing processes:
2
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller_kill', '<module>']
1
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller_kill', '<module>']
4
5
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '_maintain_pool', '_handle_workers', 'run', '_bootstrap_inner', '_bootstrap']
7
8
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '_maintain_pool', '_handle_workers', 'run', '_bootstrap_inner', '_bootstrap']

Обратите внимание на последние два списка стека, которые расходятся в _maintain_pool и в которых отсутствует интересующая меня функция mp_caller_kill.

Есть ли способ добраться до нужного стека, или эти процессы полностью разделены? Мне нужно использовать maxtasksperchild, поскольку зависимая библиотека C не освобождает память.

Спасибо.

...