-
Notifications
You must be signed in to change notification settings - Fork 959
Description
Greenlets in greenlet
always get their finally
block invoked for example when a KeyboardInterrupt
occurs. To reproduce:
import time, greenlet
def bar():
try: greenlet.getcurrent().parent.switch()
finally: print "CLEANUP BAR"
def foo():
try: time.sleep(1.0)
finally: print "CLEANUP FOO"
b1 = greenlet.greenlet(bar)
b1.switch()
b2 = greenlet.greenlet(bar)
b2.switch()
greenlet.greenlet(foo).switch()
...2 x CLEANUP BAR
+ 1 x CLEANUP FOO
gets printed when Ctrl-C
is pressed during that time.sleep(1.0)
call.
However, when using gevent
(unless time.sleep
is used, for obvious reasons), no cleanup code gets invoked whatsoever when Ctrl-C
is pressed:
from gevent import spawn, sleep
from gevent.event import Event
def bar():
try: Event().wait() # just block and switch back to main
finally: print "CLEANUP BAR"
def foo():
try: sleep(1.0)
finally: print "CLEANUP FOO" # this does get printed for obvious reasons if time.sleep is used instead
gevent.joinall([spawn(bar), spawn(bar), spawn(foo)])
...neither CLEANUP FOO
nor CLEANUP BAR
gets printed.
This is both weird, because greenlet
already handles this automatically, as well as inconsistent with standard Python semantics, which I suppose should always be sticked to. Violating fundamental semantic guarantees of the language will eventually cause confusion and problems, or at least inconvenience, such as having to manually keep track of all spawned greenlets and to kill them in a global finally
cleanup block, or in a signal handler—i.e. stuff that should be expected from gevent
.
(I've run the above code on OS X 10.7 and 64bit Python 2.7)
P.S. Also, an except KeyboardInterrupt
block never gets invoked either.