[pypy-issue] Issue #3162: GreenletExit not thrown when a greenlet is garbage-collected (pypy/pypy)

Antonio Cuni issues-reply at bitbucket.org
Wed Jan 29 12:27:27 EST 2020


New issue 3162: GreenletExit not thrown when a greenlet is garbage-collected
https://bitbucket.org/pypy/pypy/issues/3162/greenletexit-not-thrown-when-a-greenlet-is

Antonio Cuni:

```python
import greenlet
import gc

class A(object):
	def __del__(self):
		print 'A.__del__'

def g1():
	try:
		print 'g1: begin'
		a = A()
		print 'g1: switching'
		MAIN.switch()
	except greenlet.GreenletExit:
		print 'g1: GreenletExit'
	finally:
		print 'g1: finally'

def main():
	global MAIN
	MAIN = greenlet.getcurrent()
	greenlet.greenlet(g1).switch()
	gc.collect()

main()
```

These are the results on CPython and PyPy; `A.__del__` is used just to show that the greenlet is actually garbage collected.

```
$ python green.py 
g1: begin
g1: switching
g1: GreenletExit
g1: finally
A.__del__

$ pypy green.py 
g1: begin
g1: switching
A.__del__
```

‌

The following patch seems to be enough to fix the problem; however, since it’s a good practice to be very careful when dealing with greenlets and continuelets, I’d like some feeback before committing it:

```diff
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -47,6 +47,9 @@
         if parent is not None:
             self.parent = parent
 
+    def __del__(self):
+        self.throw()
+
     def switch(self, *args, **kwds):
         "Switch execution to this greenlet, optionally passing the values "
         "given as argument(s).  Returns the value passed when switching back."
```

‌




More information about the pypy-issue mailing list