将'logging'模块与'multiprocessing'模块一起使用时遇到问题。分叉的孩子最终会锁定并挂起任何日志尝试。
记录器正在使用StreamHandler进行sys.stdout和sys.stderr以及SysLogHandler(它显然从其父进程中进行了主动锁定)。
该计划如下:
我一直在各个地方获得锁定:logging._lock,SysLogHandler.lock,这取决于我尝试清理模块。
一般来说,我不喜欢与API之外的模块进行交互,但在这种情况下我大胆尝试过:
cur_logger = logging.getLogger()
cur_logger.handlers = []
logging._lock = RLock()
logging._handlerList = []
logging._handlers = {}
logging.Logger.manager.loggingDict = {}
使用以下结果(仍然锁定):
#0 0x00007fc87bceba00 in sem_wait () from /lib64/libpthread.so.0
#1 0x00007fc87bff8428 in PyThread_acquire_lock (lock=0x921970, waitflag=1) at Python/thread_pthread.h:349
#2 0x00007fc87bffc314 in lock_PyThread_acquire_lock (self=0x7fc87c3ce120, args=<value optimized out>) at Modules/threadmodule.c:47
#3 0x00007fc87bfd09d4 in call_function (f=<value optimized out>, throwflag=<value optimized out>) at Python/ceval.c:3794
#4 PyEval_EvalFrameEx (f=<value optimized out>, throwflag=<value optimized out>) at Python/ceval.c:2453
#5 0x00007fc87bfd2647 in PyEval_EvalCodeEx (co=0x7fc87c3f1828, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=1, kws=0x7fc85c003fd0, kwcount=0, defs=0x7fc87c3666e8, defcount=1, closure=0x0) at Python/ceval.c:3044
我使用相当旧的软件包,所以我的问题是它是否是以后修复的已知错误,或者有一种方法可以清除fork上的日志记录模块,以便它清除所有锁(AFAIK这些不是系统锁在叉子之后他们是无关紧要的,或者我可能做错了事。
谢谢,
版本:
Edit_1:
我在CentOS 7上做了相同的测试,它有更好的python调试器输出,并且由于SysLogHandler.lock(_RLock__count = 1)而挂起:
调试:
#0 0x00007f4fa0e7b89c in __lll_lock_wait_private () from /lib64/libc.so.6
#1 0x00007f4fa0e94fad in _L_lock_774 () from /lib64/libc.so.6
#2 0x00007f4fa0e94d65 in __check_pf () from /lib64/libc.so.6
#3 0x00007f4fa0e56fd9 in getaddrinfo () from /lib64/libc.so.6
#4 0x00007f4f98b85c92 in setipaddr (name=<optimized out>, addr_ret=addr_ret@entry=0x7f4f82ff9cf0, addr_ret_size=addr_ret_size@entry=16, af=af@entry=2)
at /usr/src/debug/Python-2.7.5/Modules/socketmodule.c:921
#5 0x00007f4f98b8781e in getsockaddrarg (s=s@entry=0x7f4f896aadb0, args=<optimized out>, addr_ret=addr_ret@entry=0x7f4f82ff9cf0, len_ret=len_ret@entry=0x7f4f82ff9c80)
at /usr/src/debug/Python-2.7.5/Modules/socketmodule.c:1321
#6 0x00007f4f98b87c63 in sock_sendto (s=0x7f4f896aadb0,
args=('<159>Jun 11 14:55:08 xdc.py.Distribute file as xdcrm.139979476948736: DEBUG [16722.139979476948736] _put:Timing SFTP stat+put of /tmp/blob.1M.bin.tmp to 10.67.145.141:/tmp/blob.1M.bin.tmp finished:True size:1048576 time:timer: 0.0349\x00', ('localhost', 514))) at /usr/src/debug/Python-2.7.5/Modules/socketmodule.c:2936
#7 0x00007f4fa1b45cf0 in call_function (oparg=<optimized out>, pp_stack=0x7f4f82ff9ea0) at /usr/src/debug/Python-2.7.5/Python/ceval.c:4408
#8 PyEval_EvalFrameEx (
f=f@entry=Frame 0x7f4f824d5a00, for file /usr/lib64/python2.7/logging/handlers.py, line 863, in emit (self=<SysLogHandler(socket=<_socketobject at remote 0x7f4f8900e980>, level=0, lock=<_RLock(_Verbose__verbose=False, _RLock__owner=139979476948736, _RLock__block=<thread.lock at remote 0x7f4fa1fd4210>, _RLock__count=1) at remote 0x7f4f887bf2d0>,
答案 0 :(得分:1)
TLDR:使用QueueHandler
(子级)和QueueListener
(父级):https://docs.python.org/3/howto/logging-cookbook.html#dealing-with-handlers-that-block
我使用Python 3.5.2和(现在)内置的多处理和日志记录模块观察到了相同的问题。
经过一番挖掘,事实证明这个问题已经存在了一段时间:https://bugs.python.org/issue6721
在3.7.4中尝试修复Python锁:https://bugs.python.org/issue36533。在测试了“固定”版本之后,我立即在文件I / O对象中偶然发现了另一个死锁。这对刷新数据有一个锁定。问题本质上是相同的-分叉的子进程继承了获得的锁而无法释放它。除了这一点发生在C代码中,这使得调试:o
更加困难我最终通过内置的队列记录帮助器使用了队列。