【问题标题】:Multiprocessing subprocesses randomly receive SIGTERMs多处理子进程随机接收 SIGTERM
【发布时间】:2019-05-05 01:18:34
【问题描述】:

我在摆弄multiprocessingsignal。 我正在创建一个池,并让工人赶上SIGTERMs。 没有明显的原因,我观察到子进程随机收到SIGTERMs。 这是一个 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

如您所见,这看起来不可预测。

那么,这些SIGTERMs 来自哪里? 这是正常的吗? 我能保证工人会完成他们的工作吗? 最后,让子进程捕获SIGTERMs 是否可以?

【问题讨论】:

    标签: python multiprocessing signals sigterm


    【解决方案1】:

    这是正常的,并且可能在您的池在离开上下文管理器时执行 __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()
    

    pool-workers 将在几行之后加入:

        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())

    如果没有必要,最好不要乱用信号处理程序。

    【讨论】:

    • 感谢您的见解。我还没有完成,但这绝对是我所期待的答案。
    【解决方案2】:

    我认为这很正常,但不能说随机消息打印。您可以获得更多信息,将其插入主目录:

    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))
    

    【讨论】:

      猜你喜欢
      • 2023-03-16
      • 1970-01-01
      • 2013-07-16
      • 2019-09-21
      • 2011-08-08
      • 2021-11-23
      • 2019-05-20
      • 2018-04-28
      • 2016-05-11
      相关资源
      最近更新 更多