Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
test_gc.py87 linesDownload Raw Back to tests
1import gc
2
3import weakref
4
5import greenlet
6
7
8from . import TestCase
9from .leakcheck import fails_leakcheck
10# These only work with greenlet gc support
11# which is no longer optional.
12assert greenlet.GREENLET_USE_GC
13
14class TestGC(TestCase):
15    def test_dead_circular_ref(self):
16        o = weakref.ref(greenlet.greenlet(greenlet.getcurrent).switch())
17        gc.collect()
18        if o() is not None:
19            import sys
20            print("O IS NOT NONE.", sys.getrefcount(o()))
21        self.assertIsNone(o())
22        self.assertFalse(gc.garbage, gc.garbage)
23
24    def test_circular_greenlet(self):
25        class circular_greenlet(greenlet.greenlet):
26            self = None
27        o = circular_greenlet()
28        o.self = o
29        o = weakref.ref(o)
30        gc.collect()
31        self.assertIsNone(o())
32        self.assertFalse(gc.garbage, gc.garbage)
33
34    def test_inactive_ref(self):
35        class inactive_greenlet(greenlet.greenlet):
36            def __init__(self):
37                greenlet.greenlet.__init__(self, run=self.run)
38
39            def run(self):
40                pass
41        o = inactive_greenlet()
42        o = weakref.ref(o)
43        gc.collect()
44        self.assertIsNone(o())
45        self.assertFalse(gc.garbage, gc.garbage)
46
47    @fails_leakcheck
48    def test_finalizer_crash(self):
49        # This test is designed to crash when active greenlets
50        # are made garbage collectable, until the underlying
51        # problem is resolved. How does it work:
52        # - order of object creation is important
53        # - array is created first, so it is moved to unreachable first
54        # - we create a cycle between a greenlet and this array
55        # - we create an object that participates in gc, is only
56        #   referenced by a greenlet, and would corrupt gc lists
57        #   on destruction, the easiest is to use an object with
58        #   a finalizer
59        # - because array is the first object in unreachable it is
60        #   cleared first, which causes all references to greenlet
61        #   to disappear and causes greenlet to be destroyed, but since
62        #   it is still live it causes a switch during gc, which causes
63        #   an object with finalizer to be destroyed, which causes stack
64        #   corruption and then a crash
65
66        class object_with_finalizer(object):
67            def __del__(self):
68                pass
69        array = []
70        parent = greenlet.getcurrent()
71        def greenlet_body():
72            greenlet.getcurrent().object = object_with_finalizer()
73            try:
74                parent.switch()
75            except greenlet.GreenletExit:
76                print("Got greenlet exit!")
77            finally:
78                del greenlet.getcurrent().object
79        g = greenlet.greenlet(greenlet_body)
80        g.array = array
81        array.append(g)
82        g.switch()
83        del array
84        del g
85        greenlet.getcurrent()
86        gc.collect()
87 
codekingpro/portable-devtools · Team Ai