Python大师我需要你的帮助.我遇到了很奇怪的行为:
空python进程挂起加入.看起来它会分配一些锁定的资源.
ENV:
> 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
我想出了流程挂起的地方.它在多处理模块中挂起,文件process.py,第269行(python3.5.3),在刷新STDERR时:
...
267 util.info('process exiting with exitcode %d' % exitcode)
268 sys.stdout.flush()
269 sys.stderr.flush()
...
如果第269行注释,则脚本始终成功完成.
我的想法:
默认情况下,logging.StreamHandler使用sys.stderr作为流.
如果在记录器将数据刷新到STDERR时分叉了进程,则进程上下文会获得一些锁定的资源,并在刷新STDERR时进一步挂起.
一些解决问题的解决方法:
>使用python2.7.我无法用python2.7重现它.也许时间阻止我重现这个问题.
>使用进程处理记录器中的消息而不是线程.
你对这种行为有什么想法吗?问题出在哪儿?难道我做错了什么?
最佳答案 看起来这种行为与此问题有关:
http://bugs.python.org/issue6721