gh-134323: Fix the new `threading.RLock.locked` method (#134368)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
Duprat 2025-05-22 15:48:24 +02:00 committed by GitHub
parent bd4046f4f8
commit 3effede97c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 29 additions and 4 deletions

View File

@ -370,6 +370,24 @@ def test_locked(self):
lock.release() lock.release()
self.assertFalse(lock.locked()) self.assertFalse(lock.locked())
def test_locked_with_2threads(self):
# see gh-134323: check that a rlock which
# is acquired in a different thread,
# is still locked in the main thread.
result = []
rlock = self.locktype()
self.assertFalse(rlock.locked())
def acquire():
result.append(rlock.locked())
rlock.acquire()
result.append(rlock.locked())
with Bunch(acquire, 1):
pass
self.assertTrue(rlock.locked())
self.assertFalse(result[0])
self.assertTrue(result[1])
def test_release_save_unacquired(self): def test_release_save_unacquired(self):
# Cannot _release_save an unacquired lock # Cannot _release_save an unacquired lock
lock = self.locktype() lock = self.locktype()

View File

@ -158,7 +158,7 @@ def __repr__(self):
except KeyError: except KeyError:
pass pass
return "<%s %s.%s object owner=%r count=%d at %s>" % ( return "<%s %s.%s object owner=%r count=%d at %s>" % (
"locked" if self._block.locked() else "unlocked", "locked" if self.locked() else "unlocked",
self.__class__.__module__, self.__class__.__module__,
self.__class__.__qualname__, self.__class__.__qualname__,
owner, owner,
@ -237,7 +237,7 @@ def __exit__(self, t, v, tb):
def locked(self): def locked(self):
"""Return whether this object is locked.""" """Return whether this object is locked."""
return self._count > 0 return self._block.locked()
# Internal methods used by condition variables # Internal methods used by condition variables

View File

@ -0,0 +1 @@
Fix the :meth:`threading.RLock.locked` method.

View File

@ -1022,6 +1022,11 @@ rlock_traverse(PyObject *self, visitproc visit, void *arg)
return 0; return 0;
} }
static int
rlock_locked_impl(rlockobject *self)
{
return PyMutex_IsLocked(&self->lock.mutex);
}
static void static void
rlock_dealloc(PyObject *self) rlock_dealloc(PyObject *self)
@ -1111,7 +1116,7 @@ static PyObject *
rlock_locked(PyObject *op, PyObject *Py_UNUSED(ignored)) rlock_locked(PyObject *op, PyObject *Py_UNUSED(ignored))
{ {
rlockobject *self = rlockobject_CAST(op); rlockobject *self = rlockobject_CAST(op);
int is_locked = _PyRecursiveMutex_IsLockedByCurrentThread(&self->lock); int is_locked = rlock_locked_impl(self);
return PyBool_FromLong(is_locked); return PyBool_FromLong(is_locked);
} }
@ -1219,10 +1224,11 @@ rlock_repr(PyObject *op)
{ {
rlockobject *self = rlockobject_CAST(op); rlockobject *self = rlockobject_CAST(op);
PyThread_ident_t owner = self->lock.thread; PyThread_ident_t owner = self->lock.thread;
int locked = rlock_locked_impl(self);
size_t count = self->lock.level + 1; size_t count = self->lock.level + 1;
return PyUnicode_FromFormat( return PyUnicode_FromFormat(
"<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%zu at %p>", "<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%zu at %p>",
owner ? "locked" : "unlocked", locked ? "locked" : "unlocked",
Py_TYPE(self)->tp_name, owner, Py_TYPE(self)->tp_name, owner,
count, self); count, self);
} }