Skip to content

Commit 5bfdbc7

Browse files
committed
Improve test
1 parent 657c68d commit 5bfdbc7

File tree

1 file changed

+41
-35
lines changed

1 file changed

+41
-35
lines changed

Lib/test/test_threading.py

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,50 +1247,56 @@ def __del__(self):
12471247
self.assertEqual(err, b"")
12481248
self.assertIn(b"all clear", out)
12491249

1250-
def test_acquire_daemon_thread_lock_in_finalization(self):
1250+
@support.subTests('lock_class_name', ['Lock', 'RLock'])
1251+
def test_acquire_daemon_thread_lock_in_finalization(self, lock_class_name):
12511252
# gh-123940: Py_Finalize() prevents other threads from running Python
12521253
# code (and so, releasing locks), so acquiring a locked lock can not
12531254
# succeed.
12541255
# We raise an exception rather than hang.
1255-
for timeout in (None, 10):
1256-
with self.subTest(timeout=timeout):
1257-
code = textwrap.dedent(f"""
1258-
import threading
1259-
import time
1256+
code = textwrap.dedent(f"""
1257+
import threading
1258+
import time
12601259
1261-
thread_started_event = threading.Event()
1260+
thread_started_event = threading.Event()
12621261
1263-
lock = threading.Lock()
1264-
def loop():
1265-
with lock:
1266-
thread_started_event.set()
1267-
while True:
1268-
time.sleep(1)
1262+
lock = threading.{lock_class_name}()
1263+
def loop():
1264+
with lock:
1265+
thread_started_event.set()
1266+
while True:
1267+
time.sleep(1)
12691268
1270-
class Cycle:
1271-
def __init__(self):
1272-
self.self_ref = self
1273-
self.thr = threading.Thread(
1274-
target=loop, daemon=True)
1275-
self.thr.start()
1276-
thread_started_event.wait()
1269+
uncontested_lock = threading.{lock_class_name}()
12771270
1278-
def __del__(self):
1279-
assert self.thr.is_alive()
1280-
try:
1281-
lock.acquire()
1282-
except PythonFinalizationError:
1283-
assert self.thr.is_alive()
1284-
print('got the correct exception!')
1271+
class Cycle:
1272+
def __init__(self):
1273+
self.self_ref = self
1274+
self.thr = threading.Thread(
1275+
target=loop, daemon=True)
1276+
self.thr.start()
1277+
thread_started_event.wait()
12851278
1286-
# Cycle holds a reference to itself, which ensures it is
1287-
# cleaned up during the GC that runs after daemon threads
1288-
# have been forced to exit during finalization.
1289-
Cycle()
1290-
""")
1291-
rc, out, err = assert_python_ok("-c", code)
1292-
self.assertEqual(err, b"")
1293-
self.assertIn(b"got the correct exception", out)
1279+
def __del__(self):
1280+
assert self.thr.is_alive()
1281+
1282+
# We *can* acquire an unlocked lock
1283+
uncontested_lock.acquire()
1284+
1285+
# Acquiring a locked one fails
1286+
try:
1287+
lock.acquire()
1288+
except PythonFinalizationError:
1289+
assert self.thr.is_alive()
1290+
print('got the correct exception!')
1291+
1292+
# Cycle holds a reference to itself, which ensures it is
1293+
# cleaned up during the GC that runs after daemon threads
1294+
# have been forced to exit during finalization.
1295+
Cycle()
1296+
""")
1297+
rc, out, err = assert_python_ok("-c", code)
1298+
self.assertEqual(err, b"")
1299+
self.assertIn(b"got the correct exception", out)
12941300

12951301
def test_start_new_thread_failed(self):
12961302
# gh-109746: if Python fails to start newly created thread

0 commit comments

Comments
 (0)