From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Wed, 8 Jul 2026 10:13:44 +0000 (+0200) Subject: [3.15] gh-153292: Fix data race in `threading.RLock.__repr__` in FT builds (GH-153299... X-Git-Tag: v3.15.0b4~82 X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;h=8c5008060f29a034d4afce7f2de6d39558b8f334;p=thirdparty%2FPython%2Fcpython.git [3.15] gh-153292: Fix data race in `threading.RLock.__repr__` in FT builds (GH-153299) (#153314) gh-153292: Fix data race in `threading.RLock.__repr__` in FT builds (GH-153299) (cherry picked from commit 1051384fcdfa88dd88d66dfc93b60aec9ca1ad2e) Co-authored-by: sobolevn --- diff --git a/Lib/test/test_free_threading/test_threading.py b/Lib/test/test_free_threading/test_threading.py new file mode 100644 index 000000000000..b5a5ca272b94 --- /dev/null +++ b/Lib/test/test_free_threading/test_threading.py @@ -0,0 +1,26 @@ +import unittest +from test.support import 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]) + + +if __name__ == "__main__": + unittest.main() diff --git a/Misc/NEWS.d/next/Library/2026-07-08-01-03-17.gh-issue-153292.oHDt3l.rst b/Misc/NEWS.d/next/Library/2026-07-08-01-03-17.gh-issue-153292.oHDt3l.rst new file mode 100644 index 000000000000..dc363e160074 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-08-01-03-17.gh-issue-153292.oHDt3l.rst @@ -0,0 +1 @@ +Fix data race in repr of :class:`threading.RLock` in free-threading build. diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 7e1884edf521..e999fe20287e 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1288,7 +1288,7 @@ static PyObject * rlock_repr(PyObject *op) { rlockobject *self = rlockobject_CAST(op); - PyThread_ident_t owner = self->lock.thread; + PyThread_ident_t owner = FT_ATOMIC_LOAD_ULLONG_RELAXED(self->lock.thread); int locked = rlock_locked_impl(self); size_t count; if (locked) {