【问题标题】:gevent: debug spinning thread?gevent:调试旋转线程?
【发布时间】:2012-10-30 19:21:18
【问题描述】:

在我基于 gevent 的程序中,我在某处有一个线程,它陷入了一个循环,类似于:

while True:
    gevent.sleep(0)

我怎样才能知道这是哪个线程?是否可以列出(并获取堆栈跟踪)正在运行的线程?

【问题讨论】:

  • 正在运行的线程的堆栈跟踪?你的意思是运行greenlets?如果是这样:stackoverflow.com/questions/12510648/…
  • gevent中没有线程,你应该尝试为那些gevent.spawn设置超时
  • ……嗯? gevent 绿色线程被称为线程——它们只是用户空间线程而不是操作系统线程。

标签: python gevent


【解决方案1】:

方法一、超时

我在我的代码中使用它来跟踪可能阻塞的greenlet。发生这种情况时会引发 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 块中。

【讨论】:

  • 抱歉,我不确定这是如何解决这个问题的,因为它假定我正在手动跟踪已启动的线程。
  • 好吧,你用 TimeOut 来结束你的工作。确保它们都没有“旋转”。还有其他方法可以检测绿让是否阻塞
【解决方案2】:

有一个官方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),
])

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-22
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 2015-01-09
    相关资源
    最近更新 更多