Skip to content

Commit e27a2d6

Browse files
committed
Merge branch 'pythongh-117688-test_no_stale_references' into nogil-integration
2 parents 66e9790 + 1ce167b commit e27a2d6

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

Lib/test/test_concurrent_futures/executor.py

+21-11
Original file line numberDiff line numberDiff line change
@@ -83,24 +83,34 @@ def test_no_stale_references(self):
8383
# references.
8484
my_object = MyObject()
8585
my_object_collected = threading.Event()
86-
my_object_callback = weakref.ref(
87-
my_object, lambda obj: my_object_collected.set())
88-
fut = self.executor.submit(my_object.my_method)
86+
def set_event():
87+
if Py_GIL_DISABLED:
88+
# gh-117688 Avoid deadlock by setting the event in a
89+
# background thread. The current thread may be in the middle
90+
# of the my_object_collected.wait() call, which holds locks
91+
# needed by my_object_collected.set().
92+
threading.Thread(target=my_object_collected.set).start()
93+
else:
94+
my_object_collected.set()
95+
my_object_callback = weakref.ref(my_object, lambda obj: set_event())
96+
# Deliberately discarding the future.
97+
self.executor.submit(my_object.my_method)
8998
del my_object
9099

91100
if Py_GIL_DISABLED:
92101
# Due to biased reference counting, my_object might only be
93102
# deallocated while the thread that created it runs -- if the
94103
# thread is paused waiting on an event, it may not merge the
95-
# refcount of the queued object. For that reason, we wait for the
96-
# task to finish (so that it's no longer referenced) and force a
97-
# GC to ensure that it is collected.
98-
fut.result() # Wait for the task to finish.
99-
support.gc_collect()
104+
# refcount of the queued object. For that reason, we alternate
105+
# between running the GC and waiting for the event.
106+
wait_time = 0
107+
collected = False
108+
while not collected and wait_time <= support.SHORT_TIMEOUT:
109+
support.gc_collect()
110+
collected = my_object_collected.wait(timeout=1.0)
111+
wait_time += 1.0
100112
else:
101-
del fut # Deliberately discard the future.
102-
103-
collected = my_object_collected.wait(timeout=support.SHORT_TIMEOUT)
113+
collected = my_object_collected.wait(timeout=support.SHORT_TIMEOUT)
104114
self.assertTrue(collected,
105115
"Stale reference not collected within timeout.")
106116

0 commit comments

Comments
 (0)