Python专家我需要您的帮助。我遇到了非常奇怪的行为:
空python进程挂起加入。看起来它派生了一些锁定的资源。

环境:

  • Python版本:3.5.3
  • 操作系统:Ubuntu 16.04.2 LTS
  • 内核:4.4.0-75通用

  • 问题描述:

    1)我有一个带线程的记录器,可以在后台处理消息并为此线程排队。 Logger source code(有点简化)。

    2)我有一个使用记录器的简单脚本(只需代码即可显示我的问题):
    import os
    from multiprocessing import Process
    from my_logging import get_logger
    
    
    def func():
        pass
    
    
    if __name__ == '__main__':
    
        logger = get_logger(__name__)
        logger.start()
        for _ in range(2):
            logger.info('message')
    
        proc = Process(target=func)
        proc.start()
        proc.join(timeout=3)
        print('TEST PROCESS JOINED: is_alive={0}'.format(proc.is_alive()))
    
        logger.stop()
        print('EXIT')
    

    有时,该测试脚本会挂起。脚本卡在加入过程“proc”上(脚本完成执行时)。测试过程“proc”保持有效。

    要重现此问题,您可以循环运行脚本:
    $ for i in {1..100} ; do /opt/python3.5.3/bin/python3.5 test.py ; done
    

    调查:

    Strace显示以下内容:
    strace: Process 25273 attached
    futex(0x2275550, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, ffffffff
    

    我找出了进程挂起的地方。它卡在冲洗STDERR的多处理模块文件process.py,第269行(python3.5.3)中:
    ...
    267    util.info('process exiting with exitcode %d' % exitcode)
    268    sys.stdout.flush()
    269    sys.stderr.flush()
    ...
    

    如果第269行注释,该脚本将始终成功完成。

    我的想法:

    默认情况下,logging.StreamHandler使用sys.stderr作为流。

    如果记录器将数据刷新到STDERR时已经 fork 了进程,则进程上下文将获取一些锁定的资源,并进一步挂起在刷新STDERR上。

    一些解决问题的方法:
  • 使用python2.7。我无法用python2.7复制它。也许时间安排使我无法重现该问题。
  • 使用进程在记录器中而不是线程中处理消息。

  • 您对此行为有任何想法吗?问题出在哪儿?难道我做错了什么?

    最佳答案

    似乎此行为与此问题有关:http://bugs.python.org/issue6721

    关于python - 空python进程卡在连接[sys.stderr.flush()]上,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44069717/

    10-14 18:08
    查看更多