Skip to content

Commit 241b0fc

Browse files
committed
gh-156910: Add free-threading regression test for type_set_abstractmethods() deadlock
1 parent 2ef3728 commit 241b0fc

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

‎Lib/test/test_free_threading/test_type.py‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import abc
2+
import collections.abc
3+
import gc
14
import threading
25
import unittest
36

@@ -401,6 +404,41 @@ class B(A):
401404
with threading_helper.start_threads(threads):
402405
pass
403406

407+
def test_abstractmethods_and_register(self):
408+
# gh-156910: creating an ABC sets __abstractmethods__ and
409+
# Sequence.register() sets type flags recursively. Both stop the
410+
# world while holding the type lock. type_set_abstractmethods() did
411+
# not pin the type lock, so it could be released while waiting for
412+
# the stop-the-world mutex and then deadlock re-acquiring it. The
413+
# gc.collect() thread adds contention on the stop-the-world mutex,
414+
# which is needed to hit the deadlock.
415+
done = threading.Event()
416+
417+
def make_abcs():
418+
for _ in range(ITERS):
419+
class C(abc.ABC):
420+
@abc.abstractmethod
421+
def f(self):
422+
pass
423+
424+
def register():
425+
for _ in range(ITERS):
426+
collections.abc.Sequence.register(type("S", (), {}))
427+
428+
def collect():
429+
while not done.is_set():
430+
gc.collect()
431+
432+
workers = [Thread(target=make_abcs) for _ in range(NTHREADS)]
433+
workers += [Thread(target=register) for _ in range(NTHREADS)]
434+
collector = Thread(target=collect)
435+
with threading_helper.start_threads([collector]):
436+
try:
437+
with threading_helper.start_threads(workers):
438+
pass
439+
finally:
440+
done.set()
441+
404442
def test_class_creation_with_concurrent_setattr(self):
405443
# Creating a class resolves its slots from the dicts along the MRO
406444
# while holding the type lock, before the class is reachable from
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add a free-threading regression test for the deadlock between creating an
2+
abstract base class and :meth:`ABCMeta.register <abc.ABCMeta.register>`.

0 commit comments

Comments
 (0)