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.

static PyObject *
rlock_repr(PyObject *op)
{
rlockobject *self = rlockobject_CAST(op);
PyThread_ident_t owner = self->lock.thread;
int locked = 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 _thread
from threading import Thread

r = _thread.RLock()

def thread1():
    for _ in range(20000):
        try:
            repr(r)
        except Exception:
            pass

def thread2():
    for _ in range(20000):
        r.acquire()
        r.release()

threads  = [Thread(target=thread1) for _ in range(6)]
threads += [Thread(target=thread2)   for _ in range(2)]
for t in threads: t.start()
for t in threads: 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

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions