Gevent: Is it safe to set gevent.event.Event in another native thread

Created on 14 Nov 2016  ยท  2Comments  ยท  Source: gevent/gevent

  • gevent version: 1.1.2
  • Python version: 2.7.12
  • Operating System: RHEL 5

Description:

if i have two native threads,
one thread runs gevent loop,
and has a greenlet waiting for an event named MyE to be set (gevent.event.Event not threading.Event ),
another thread(write by c) call a function in which set the MyE when something happen .
I tested it worked, but not sure it is real safe or any other better solutions?

Is the thread in docs said a native thread or moneky_patched thread
"""If the internal flag is true on entry, return immediately. Otherwise, block until another thread (greenlet) calls set() to set the flag to true"""

What I've run:

from gevent.event import Event
eee = Event()

def callback(xx):
    """ 
        running in another thread
    """
    global eee 
    print("callback args is %s "% xx) 
    eee.set() 

def waiting(e):
    while True:
        e.wait()
        print "e is set"
        e.clear()

gevent.spawn(waiting, eee).join()
Question

Most helpful comment

LIke most gevent objects, Event has thread-affinity, meaning it is only meant to be used from the thread where it was created (in your example, that's the main thread).

Trying to set() an Event from a different thread may appear to work almost all of the time, but it does have race conditions. To the extent that it does work, it's only because of the Python GIL (global interpreter lock) that prevents two Python threads from running at the same time. In other words, you're _probably_ safe to do that (especially if you stick to one thread doing the set), but there are no guarantees, and it could change any time the interpreter or gevent does. You'll have to decide if you're comfortable with that.

In contrast, trying to wait() on an Event from a different thread will result in raising a greenlet.error.

One way to achieve a safer notify-another-thread action is to use a non-blocking pipe. set becomes writing a byte to the pipe, wait becomes reading a byte from the pipe. The async watcher does basically this.

All 2 comments

LIke most gevent objects, Event has thread-affinity, meaning it is only meant to be used from the thread where it was created (in your example, that's the main thread).

Trying to set() an Event from a different thread may appear to work almost all of the time, but it does have race conditions. To the extent that it does work, it's only because of the Python GIL (global interpreter lock) that prevents two Python threads from running at the same time. In other words, you're _probably_ safe to do that (especially if you stick to one thread doing the set), but there are no guarantees, and it could change any time the interpreter or gevent does. You'll have to decide if you're comfortable with that.

In contrast, trying to wait() on an Event from a different thread will result in raising a greenlet.error.

One way to achieve a safer notify-another-thread action is to use a non-blocking pipe. set becomes writing a byte to the pipe, wait becomes reading a byte from the pipe. The async watcher does basically this.

Many thanks ๏ผ @jamadden

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SiegelDaniel picture SiegelDaniel  ยท  7Comments

jamadden picture jamadden  ยท  6Comments

jamadden picture jamadden  ยท  9Comments

arcivanov picture arcivanov  ยท  5Comments

ClericPy picture ClericPy  ยท  6Comments