gevent: отладить вращающийся поток?

В моей программе на основе gevent у меня где-то есть поток, который зацикливается примерно так:

while True:
    gevent.sleep(0)

Как понять, что это за ветка? Можно ли перечислить (и получить трассировку стека) запущенных потоков?


person David Wolever    schedule 30.10.2012    source источник
comment
Трассировка стека для запущенных потоков? Вы имеете в виду запуск гринлетов? Если да: stackoverflow.com/questions/12510648/   -  person kkurian    schedule 17.11.2013
comment
В gevent нет потоков, попробуйте установить тайм-аут для этих gevent.spawn.   -  person Zhuo.M    schedule 17.06.2014
comment
… ха? gevent green threads называются потоками — это просто потоки пользовательского пространства, а не потоки ОС.   -  person David Wolever    schedule 17.06.2014


Ответы (2)


способ 1. Таймаут

Я использую это в своем коде, чтобы отслеживать гринлеты, которые потенциально блокируются. Когда это происходит, возникает NodeTaskTimeout. Просто оберните свои задания в Timeout или предоставьте им объект TimeOut.

 with Timeout(90, False):
        task_jobs.join()
    
    if task_jobs:
        print 'task jobs killed', task_jobs
        task_jobs.kill()
        if settings.DEBUG:
            raise NodeTaskTimeout

Эта распечатка выводит задачу, если она зависает/блокируется/занимает слишком много времени. Особенно неприятны те задания, которые зависят друг от друга и вызывают взаимоблокировку job1 /thread -> job2/thread2 -> job3/thread3 и job/thread3 завершается только тогда, когда выполняется job1, чего никогда не произойдет, потому что job2 не выполнен, а job2 не выполнен. сделано из-за того, что job3 не выполнен .. вы поняли ;)

Мехтод 2

http://www.rfk.id.au/blog/entry/detect-gevent-blocking-with-greenlet-settrace/

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

person Stephan    schedule 04.09.2014
comment
Извините, но я не уверен, как это решает вопрос, поскольку предполагает, что я вручную отслеживаю, какие потоки были запущены. - person David Wolever; 04.09.2014
comment
Ну, вы оборачиваете свои задания с помощью TimeOut. чтобы убедиться, что ни один из них не вращается. Существуют и другие способы определить, блокирует ли зеленый цвет - person Stephan; 05.09.2014

Существует официальный API для проверки блокировки, он определит точную строку, вызвавшую блокировку, проверьте пример кода ниже:

# gevent        1.3.7
# greenlet      0.4.15
# zope.event    4.4
import gevent
from gevent import config, get_hub
from gevent.events import IEventLoopBlocked
import logging
from pprint import pformat
import time
import zope.event

# initial logging
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)

# setup gevent config
# enable the monitor thread
config.monitor_thread = True
config.max_blocking_time = 4

# start the monitor thread
hub = get_hub()
monitor = hub.start_periodic_monitoring_thread()

# register the event to logging system
def g(event):
    log.error('Greenlet: {}, exceed the max blocking time: {}'.format(event.greenlet, event.blocking_time))
    log.error(pformat(event.info))
event = IEventLoopBlocked()
zope.event.subscribers.append(g)

# you can also create you own monitoring function
# def check(hub):
#     print('< periodic check in monitoring thread >')
#
# monitor.add_monitoring_function(check, 1)

def gl1():
    # use time.sleep to trigger block
    log.info('block at gl1 for 2 seconds')
    time.sleep(2)
    log.info('leave gl1 now')

def gl2():
    # use time.sleep to trigger block
    log.info('block at gl2 for 6 seconds should be detected')
    time.sleep(6)
    log.info('leave gl2 now')

def gl3():
    # gevent.sleep will not block
    log.info('gl3 will not block since it use gevent.sleep')
    gevent.sleep(8)
    log.info('leave gl3 now')


gevent.joinall([
    gevent.spawn(gl3),
    gevent.spawn(gl1),
    gevent.spawn(gl2),
])

Я надеюсь, что это помогает!

person panda912    schedule 08.03.2020