Skip to content

_thread.lock.release() is not thread-safe in free-threaded builds #117721

Closed
@mpage

Description

@mpage

Bug report

Bug description:

The implementation of _thread.lock.release() manipulates the locked field in a thread-unsafe way (this may be called by a thread that does not hold the lock) in free-threaded builds:

static PyObject *
lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
{
/* Sanity check: the lock must be locked */
if (!self->locked) {
PyErr_SetString(ThreadError, "release unlocked lock");
return NULL;
}
self->locked = 0;
PyThread_release_lock(self->lock_lock);
Py_RETURN_NONE;
}

We're choosing to punt on this for 3.13 since this should only be problematic for contended unlocks. We can revisit this for 3.13 if it turns out to be an issue in practice.

Post 3.13 we would like to change the underlying lock to be a PyMutex and replace the implementation with something like:

static PyObject *
lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
{
    /* Sanity check: the lock must be locked */
    if (_PyMutex_TryUnlock(&self->mutex) < 0) {
        PyErr_SetString(ThreadError, "release unlocked lock");
        return NULL;
    }

    Py_RETURN_NONE;
}

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions