说起这个需求,其实是来自于实现一个Gevent内的代码执行器的逻辑。

这个逻辑要求定时运行某个用户的callback,但是必须不能一直执行这个callback,所以要有Timeout,在Timeout到达的时候,自动kill掉用户的Greenlet.

Gevent自带一个Timeout的实现,同时Greenlet也都表现为DaemonThread运行。

但是经过尝试发现,Gevent的Timeout在这种场景下无法工作。

import gevent
import time
 
 
def fucking_loop():
    while True:
        pass
 
 
def fucking_loop_with_timeout():
    with gevent.Timeout(10):
        while True:
            pass
 
 
def fail_to_kill():
    deadline = time.time() + 10
    
    thread = gevent.spawn(fucking_loop)
    
    while deadline > time.time():
        # gevent.sleep will switch out of main thread
        gevent.sleep(1)
    
    # This line of code will never been executed
    # because gevent will not switch to main thread.
    thread.kill()
 
 
def fail_to_kill_2():
    deadline = time.time() + 10
 
    thread = gevent.spawn(fucking_loop)
    
    # Will never timeout because of the same reason 
    fucking_loop_with_timeout()
 
    # This line of code will never been executed
    # because gevent will not switch to main thread.
    thread.kill()

Gevent的Greenlet切换都是发生在等待IO的时候,并不会在需要所有CPU的地方发生切换,因此,对于空的While Loop,Gevent主线程或者说切换器,永远没有机会执行,因为空的while loop会一直吃CPU,而不会触发switch,这样Timeout的执行也就无从谈起了。

关于Gevent切换的讨论,可以参见:

https://groups.google.com/forum/#!topic/gevent/eBj9YQYGBbc

http://stackoverflow.com/questions/23513472/how-to-stop-a-gevent-micro-thread-when-it-in-a-while-loop

Gevent无法处理这种业务代码的情况下,有没有别的思路或者工具可以处理Timeout这种场景呢?

答案是操作系统的Signal API。

https://docs.python.org/2/library/signal.html

操作系统的SignalAPI会将Callback注册到操作系统的Timer里,这个Timer不受用户态调度器Gevent(Greenlet)的影响,因此不论Gevent的实现逻辑是什么样子的,操作系统都会在时间条件符合设置的时候,调用我们之前注册的Callback,这样一来,我们想要的Timeout功能就可以合理实现了。

最终可以工作的 版本:

import gevent
import time
 
 
def fucking_loop():
    while True:
        pass
 
 
def kill_fucking_loop_works():
    import signal
    timeout = 10
 
    thread = gevent.spawn(fucking_loop)
 
    def kill_thread(*args, **kwargs):
        if not thread.dead:
            thread.kill(timeout=1)
 
    signal.signal(signal.SIGALRM, kill_thread)
    signal.alarm(int(timeout))

标签: gevent, corutine

已有 8 条评论

  1. 文章的确不错啊https://www.cscnn.com/

  2. 你的文章让我感受到了正能量,非常棒! https://www.4006400989.com/qyvideo/90868.html

  3. 你的文章充满了智慧,让人敬佩。 https://www.4006400989.com/qyvideo/36305.html

  4. 《金粉世家》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/35345.html

  5. 《红色追击令》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/35346.html

  6. 《北京55日》战争片高清在线免费观看:https://www.jgz518.com/xingkong/89886.html

  7. 你的才华让人瞩目,期待你的更多文章。 https://www.4006400989.com/qyvideo/83561.html

  8. 《我是代办》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/93545.html

添加新评论