| 74 | pass |
| 75 | |
| 76 | def test_derived_cycle_dealloc(self): |
| 77 | # http://bugs.python.org/issue6990 |
| 78 | class Local(self._local): |
| 79 | pass |
| 80 | locals = None |
| 81 | passed = False |
| 82 | e1 = threading.Event() |
| 83 | e2 = threading.Event() |
| 84 | |
| 85 | def f(): |
| 86 | nonlocal passed |
| 87 | # 1) Involve Local in a cycle |
| 88 | cycle = [Local()] |
| 89 | cycle.append(cycle) |
| 90 | cycle[0].foo = 'bar' |
| 91 | |
| 92 | # 2) GC the cycle (triggers threadmodule.c::local_clear |
| 93 | # before local_dealloc) |
| 94 | del cycle |
| 95 | support.gc_collect() # For PyPy or other GCs. |
| 96 | e1.set() |
| 97 | e2.wait() |
| 98 | |
| 99 | # 4) New Locals should be empty |
| 100 | passed = all(not hasattr(local, 'foo') for local in locals) |
| 101 | |
| 102 | t = threading.Thread(target=f) |
| 103 | t.start() |
| 104 | e1.wait() |
| 105 | |
| 106 | # 3) New Locals should recycle the original's address. Creating |
| 107 | # them in the thread overwrites the thread state and avoids the |
| 108 | # bug |
| 109 | locals = [Local() for i in range(10)] |
| 110 | e2.set() |
| 111 | t.join() |
| 112 | |
| 113 | self.assertTrue(passed) |
| 114 | |
| 115 | def test_arguments(self): |
| 116 | # Issue 1522237 |