mirror of
https://github.com/python/cpython
synced 2026-11-06 09:02:40 +03:00
Preserve active attach waiters across successive stop-the-world pauses
so a tight collection loop cannot keep them from making progress.
Keep the waiter-aware resume operation local to pystate.c because this
branch does not have the newer BRC suspend and resume helpers.
(cherry picked from commit f156510960)
63 lines
1.7 KiB
Python
63 lines
1.7 KiB
Python
import unittest
|
|
import textwrap
|
|
|
|
from test import support
|
|
from test.support import script_helper, threading_helper
|
|
|
|
threading_helper.requires_working_threading(module=True)
|
|
|
|
|
|
class TestRlock(unittest.TestCase):
|
|
def test_repr_race(self):
|
|
# gh-153292
|
|
import _thread
|
|
r = _thread.RLock()
|
|
|
|
def repr_thread():
|
|
for _ in range(2000):
|
|
repr(r)
|
|
|
|
def mutate_thread():
|
|
for _ in range(2000):
|
|
r.acquire()
|
|
r.release()
|
|
|
|
threading_helper.run_concurrently([repr_thread, mutate_thread])
|
|
|
|
|
|
class TestThreadState(unittest.TestCase):
|
|
@support.requires_subprocess()
|
|
def test_tight_stw_loop_does_not_starve_attach(self):
|
|
script = textwrap.dedent(f"""
|
|
import faulthandler
|
|
|
|
faulthandler.dump_traceback_later({support.SHORT_TIMEOUT}, exit=True)
|
|
|
|
import _testinternalcapi
|
|
import threading
|
|
import time
|
|
|
|
started = threading.Event()
|
|
stop = threading.Event()
|
|
|
|
def stop_the_world():
|
|
_testinternalcapi.test_stop_the_world()
|
|
started.set()
|
|
while not stop.is_set():
|
|
_testinternalcapi.test_stop_the_world()
|
|
|
|
thread = threading.Thread(target=stop_the_world)
|
|
thread.start()
|
|
started.wait()
|
|
# Each reattachment must make progress between consecutive pauses.
|
|
for _ in range(50):
|
|
time.sleep(0.02)
|
|
stop.set()
|
|
thread.join()
|
|
faulthandler.cancel_dump_traceback_later()
|
|
""")
|
|
script_helper.assert_python_ok("-X", "gil=0", "-c", script)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|