Skip to content

Add fallback implementation of PyCriticalSection_BeginMutex for Python 3.13t#5981

Open
XuehaiPan wants to merge 18 commits intopybind:masterfrom
XuehaiPan:fix-py313t
Open

Add fallback implementation of PyCriticalSection_BeginMutex for Python 3.13t#5981
XuehaiPan wants to merge 18 commits intopybind:masterfrom
XuehaiPan:fix-py313t

Conversation

@XuehaiPan
Copy link
Contributor

Description

Fix #5971 (comment)

Suggested changelog entry:

  • Placeholder.

# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x030E00C1 // 3.14.0rc1
PyCriticalSection_BeginMutex(&cs, &mutex.mutex);
# else
_PyCriticalSection_BeginMutex(_PyThreadState_GET(), &cs, &mutex.mutex);
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this will compile on 3.13 without additional changes. _PyCriticalSection_BeginMutex is in an inline function in an internal-only header (pycore_critical_section.h).

I think we should use PyAPI_FUNC(void) _PyCriticalSection_BeginSlow(PyCriticalSection *c, PyMutex *m); instead. It's not inline, but you'll need to declare it above.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, we'll still have the race condition with py::make_key_iterator in 3.13 due to the critical section implementation behaving differently in 3.13, but otherwise it should preserve compatibility.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, we'll still have the race condition with py::make_key_iterator in 3.13 due to the critical section implementation behaving differently in 3.13, but otherwise it should preserve compatibility.

I think that's OK. We just want to limp through enough to make the pybind11 v3.0.2 release without breaking what worked with Python 3.13t before.

@XuehaiPan XuehaiPan changed the title Add failback implementation of PyCriticalSection_BeginMutex for Python 3.13t Add fallback implementation of PyCriticalSection_BeginMutex for Python 3.13t Feb 2, 2026
@XuehaiPan XuehaiPan requested a review from henryiii as a code owner February 3, 2026 11:46
`_PyCriticalSection_BeginSlow` is a private CPython function not exported
on Linux. For Python < 3.14.0rc1, use direct `mutex.lock()`/`mutex.unlock()`
instead of critical section APIs.
@XuehaiPan XuehaiPan requested review from colesbury and rwgk February 3, 2026 13:10
@henryiii
Copy link
Collaborator

henryiii commented Feb 5, 2026

I think this hangs. I think we probably should do nothing on 3.13t, rather than trying to also have a lock?

@colesbury
Copy link
Contributor

What was the issue with _PyCriticalSection_BeginSlow?

Refactor pycritical_section into a unified class with internal version
checks instead of using a type alias fallback. Skip locking in
make_iterator_impl for Python < 3.14.0rc1 to avoid deadlock during
type registration, as pycritical_section cannot release the mutex
during Python callbacks without PyCriticalSection_BeginMutex.
@XuehaiPan
Copy link
Contributor Author

What was the issue with _PyCriticalSection_BeginSlow?

There is a linkage issue on Linux.

@pytest.mark.skipif(
sys.platform.startswith("emscripten"), reason="Requires loadable modules"
)
@pytest.mark.xfail(env.MUSLLINUX, reason="Flaky on musllinux", strict=False)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this a known errata with the current fix?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@colesbury
Copy link
Contributor

colesbury commented Feb 5, 2026

You would need to copy the forward declaration from Python (PyAPI_FUNC(void)). I don't think extern "C" is always sufficient because of symbol visibility:

https://github.com/python/cpython/blob/60403a5409ff2c3f3b07dd2ca91a7a3e096839c7/Include/internal/pycore_critical_section.h#L91-L92

But if you get the mutex working, that seems fine too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants