Skip to content

Commit c3d4f27

Browse files
committed
gh-156910: Add free-threading regression test for type_set_abstractmethods() deadlock
1 parent b89f1c9 commit c3d4f27

2 files changed

Lines changed: 38 additions & 0 deletions

File tree

‎Lib/test/test_free_threading/test_type.py‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import abc
2+
import collections.abc
13
import gc
24
import threading
35
import unittest
@@ -569,6 +571,40 @@ def subsetter():
569571
self.assertIn(C, A.__subclasses__())
570572
self.assertNotIn(C, B.__subclasses__())
571573

574+
def test_abstractmethods_and_register(self):
575+
# gh-156910: creating an ABC sets __abstractmethods__ and
576+
# Sequence.register() sets type flags recursively. Both take the type
577+
# lock and stop the world, and racing them used to deadlock between
578+
# the type lock and the stop-the-world mutex. The gc.collect() thread
579+
# adds contention on the stop-the-world mutex, which is needed to hit
580+
# the deadlock.
581+
done = threading.Event()
582+
583+
def make_abcs():
584+
for _ in range(ITERS):
585+
class C(abc.ABC):
586+
@abc.abstractmethod
587+
def f(self):
588+
pass
589+
590+
def register():
591+
for _ in range(ITERS):
592+
collections.abc.Sequence.register(type("S", (), {}))
593+
594+
def collect():
595+
while not done.is_set():
596+
gc.collect()
597+
598+
workers = [Thread(target=make_abcs) for _ in range(NTHREADS)]
599+
workers += [Thread(target=register) for _ in range(NTHREADS)]
600+
collector = Thread(target=collect)
601+
with threading_helper.start_threads([collector]):
602+
try:
603+
with threading_helper.start_threads(workers):
604+
pass
605+
finally:
606+
done.set()
607+
572608
def test_class_creation_with_concurrent_setattr(self):
573609
# Creating a class resolves its slots from the dicts along the MRO
574610
# 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)