Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

gh-134009: Expose PyMutex_IsLocked in the public C API #134365

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
Loading
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions 12 Doc/c-api/init.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2291,6 +2291,18 @@ The C-API provides a basic mutual exclusion lock.

.. versionadded:: 3.13

.. c:function:: int PyMutex_IsLocked(PyMutex *m)

Returns one if the mutex *m* is currently locked, zero otherwise.
colesbury marked this conversation as resolved.
Show resolved Hide resolved

.. note::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should consider promoting this note to a warning. I feel like a note doesn't address the actual severity of using this for control flow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the note is appropriate. The API does exactly what it name suggests.

Copy link
Member

@ZeroIntensity ZeroIntensity May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but it's a pitfall that I commonly see people fall into, and it can cause crashes. I'm a little worried that a note is something that people will skip over, or at least not fully mentally process. Is there an API for precedent you had in mind?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where have you seen people fall into this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On GitHub, the two best examples off the top of my head are #125908 and #134289 (comment). It's a mistake I could definitely see some users of the C API making, but I'll be able to live with it as a note too.


This function is intended for use in assertions and debugging only and
should not be used to make concurrency control decisions, as the lock
state may change immediately after the check.

.. versionadded:: 3.14
vstinner marked this conversation as resolved.
Show resolved Hide resolved

.. _python-critical-section-api:

Python Critical Section API
Expand Down
11 changes: 11 additions & 0 deletions 11 Include/cpython/lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ PyAPI_FUNC(void) PyMutex_Lock(PyMutex *m);
// exported function for unlocking the mutex
PyAPI_FUNC(void) PyMutex_Unlock(PyMutex *m);

// exported function for unlocking the mutex
colesbury marked this conversation as resolved.
Show resolved Hide resolved
PyAPI_FUNC(int) PyMutex_IsLocked(PyMutex *m);

// Locks the mutex.
//
// If the mutex is currently locked, the calling thread will be parked until
Expand All @@ -61,3 +64,11 @@ _PyMutex_Unlock(PyMutex *m)
}
}
#define PyMutex_Unlock _PyMutex_Unlock

// Checks if the mutex is currently locked.
static inline int
_PyMutex_IsLocked(PyMutex *m)
{
return (_Py_atomic_load_uint8(&m->_bits) & _Py_LOCKED) != 0;
}
#define PyMutex_IsLocked _PyMutex_IsLocked
7 changes: 0 additions & 7 deletions 7 Include/internal/pycore_lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@ PyMutex_LockFast(PyMutex *m)
return _Py_atomic_compare_exchange_uint8(lock_bits, &expected, _Py_LOCKED);
}

// Checks if the mutex is currently locked.
static inline int
PyMutex_IsLocked(PyMutex *m)
{
return (_Py_atomic_load_uint8(&m->_bits) & _Py_LOCKED) != 0;
}

// Re-initializes the mutex after a fork to the unlocked state.
static inline void
_PyMutex_at_fork_reinit(PyMutex *m)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Expose :c:func:`PyMutex_IsLocked` as part of the public C API.
vstinner marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 8 additions & 0 deletions 8 Python/lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,3 +619,11 @@ PyMutex_Unlock(PyMutex *m)
Py_FatalError("unlocking mutex that is not locked");
}
}


#undef PyMutex_IsLocked
int
PyMutex_IsLocked(PyMutex *m)
{
return _PyMutex_IsLocked(m);
}
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.