правильная очистка модуля логирования на вилке (многопроцессорный модуль) - PullRequest
0 голосов
/ 08 июня 2018

У меня проблема при использовании модуля 'logging' вместе с модулем 'multiprocessing'.Разветвленный дочерний элемент заканчивается блокировкой и зависает при любой попытке журнала.

Регистратор использует StreamHandler для sys.stdout и sys.stderr и SysLogHandler (который, по-видимому, несет активную блокировку от своего родителя).

Схема выглядит следующим образом:

  • рабочие процессы реализованы в виде потоков (Thread)
  • рабочие задания, выполняемые рабочими, являются подпроцессами (Process)

Я продолжаю получать блокировки в разных местах, таких как: 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 это не системные блокировки и они не имеют отношения к разветвлению после fork), или, возможно, я что-то делаю неправильно.

Спасибо,

Версии:

  • python: python-2.6.6-66.el6_8.x86_64
  • logging. версия : 0.5.0.5
  • многопроцессорная. версия : 0.70a1

Edit_1:

Я провел такой же тест на CentOS 7, который имеет лучший вывод отладчика для python, и зависает из-за SysLogHandler.lock (_RLock__count = 1):

  • Должен ли я сосредоточиться на отслеживании экземпляра SyLogHandler, который был перенесен в дочерний элемент
  • , или есть другая запись в журнал, подходящая для «многопроцессорной обработки»
  • или блокировка вызвана каким-либомой код

Отладка:

#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>,

1 Ответ

0 голосов
/ 05 июля 2019

TLDR: используйте QueueHandler (дочерний) и QueueListener (родительский): https://docs.python.org/3/howto/logging-cookbook.html#dealing-with-handlers-that-block

Я наблюдал ту же проблему при использовании Python 3.5.2 и (теперь) встроенной многопроцессорной обработки и ведения журналаmodules.

После некоторого копания выясняется, что эта проблема давно известна: https://bugs.python.org/issue6721

Попытка исправить блокировки Python была предпринята в 3.7.4: https://bugs.python.org/issue36533. Сразу после тестирования «исправленной» версии я наткнулся на еще один тупик, на этот раз в объекте ввода-вывода файла.У этого есть замок вокруг сброса данных.Проблема по сути та же - разветвленный дочерний процесс наследует полученную блокировку без возможности ее снятия.За исключением того, что это происходит в коде C, что усложняет отладку: o

Я закончил тем, что использовал очередь через встроенные помощники ведения журнала очереди.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...