Skip to content

Data race in repr() of _thread.RLock #153292

Description

@Naserume

Bug report

Bug description:

In the free-threaded build, rlock_repr reads the recursive lock's owner with plain loads to build the repr string, while acquire/release/_acquire_restore write the owner with atomic stores.

staticPyObject*
rlock_repr(PyObject*op)
{
rlockobject*self=rlockobject_CAST(op);
PyThread_ident_towner=self->lock.thread;
intlocked=rlock_locked_impl(self);

The reader side is not atomic, so a repr() concurrent with acquire() is a data race on the owner field.

Reproducer:

import_threadfromthreadingimportThreadr=_thread.RLock()
defthread1():
for_inrange(20000):
try:
repr(r)
exceptException:
passdefthread2():
for_inrange(20000):
r.acquire()
r.release()
threads= [Thread(target=thread1) for_inrange(6)]
threads+= [Thread(target=thread2) for_inrange(2)]
fortinthreads: t.start()
fortinthreads: t.join()

TSAN Report:

==================
WARNING: ThreadSanitizer: data race (pid=40273)
Read of size 8 at 0x7fffb6600f38 by thread T1:
#0 rlock_repr /cpython/./Modules/_threadmodule.c:1291:41 #1 PyObject_Repr /cpython/Objects/object.c:784:11 #2 builtin_repr /cpython/Python/bltinmodule.c:2677:12 #3 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:2712:35
...
Previous atomic write of size 8 at 0x7fffb6600f38 by thread T7:
#0 _Py_atomic_store_ullong_relaxed /cpython/./Include/cpython/pyatomic_gcc.h:518:3 #1 _PyRecursiveMutex_LockTimed /cpython/Python/lock.c:439:9 #2 _thread_RLock_acquire_impl /cpython/./Modules/_threadmodule.c:1102:22 #3 _thread_RLock_acquire /cpython/./Modules/clinic/_threadmodule.c.h:418:20 #4 _PyCallMethodDescriptorFastWithKeywords_StackRef /cpython/Python/ceval.c:883:11 #5 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:4205:35
...
SUMMARY: ThreadSanitizer: data race /cpython/./Modules/_threadmodule.c:1291:41 in rlock_repr
==================

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions