如果使用`maxtasksperchild`,Python多处理池会修改堆栈

时间:2019-05-24 01:38:10

标签: python-3.x multiprocessing stack-trace

我正在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库没有释放内存。

谢谢。

0 个答案:

没有答案