Fix race condition with py::make_key_iterator in free threading (#5971)
* Fix race condition with py::make_key_iterator in free threading
The creation of the iterator class needs to be synchronized.
* style: pre-commit fixes
* Use PyCriticalSection_BeginMutex instead of recursive mutex
* style: pre-commit fixes
* Make pycritical_section non-copyable and non-movable
The pycritical_section class is a RAII wrapper that manages a Python
critical section lifecycle:
- Acquires the critical section in the constructor via
PyCriticalSection_BeginMutex
- Releases it in the destructor via PyCriticalSection_End
- Holds a reference to a pymutex
Allowing copy or move operations would be dangerous:
1. Copy: Both the original and copied objects would call
PyCriticalSection_End on the same PyCriticalSection object in their
destructors, leading to double-unlock and undefined behavior.
2. Move: The moved-from object's destructor would still run and attempt
to end the critical section, while the moved-to object would also try
to end it, again causing double-unlock.
This follows the same pattern used by other RAII lock guards in the
codebase, such as gil_scoped_acquire and gil_scoped_release, which also
explicitly delete copy/move operations to prevent similar issues.
By explicitly deleting these operations, we prevent accidental misuse
and ensure the critical section is properly managed by a single RAII
object throughout its lifetime.
* Drop Python 3.13t support from CI
Python 3.13t was experimental, while Python 3.14t is not. This PR
uses PyCriticalSection_BeginMutex which is only available in Python
3.14+, making Python 3.13t incompatible with the changes.
Removed all Python 3.13t CI jobs:
- ubuntu-latest, 3.13t (standard-large matrix)
- macos-15-intel, 3.13t (standard-large matrix)
- windows-latest, 3.13t (standard-large matrix)
- manylinux job testing 3.13t
This aligns with the decision to drop Python 3.13t support as
discussed in PR #5971.
* Add Python 3.13 (default) replacement jobs for removed 3.13t jobs
After removing Python 3.13t support (incompatible with PyCriticalSection_BeginMutex
which requires Python 3.14+), we're adding replacement jobs using Python 3.13
(default) to maintain test coverage in key dimensions:
1. ubuntu-latest, Python 3.13: C++20 + DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
- Replaces: ubuntu-latest, 3.13t with same config
- Maintains coverage for this specific configuration combination
2. macos-15-intel, Python 3.13: C++11
- Replaces: macos-15-intel, 3.13t with same config
- Maintains macOS coverage for Python 3.13
3. manylinux (musllinux), Python 3.13: GIL testing
- Replaces: manylinux, 3.13t job
- Maintains manylinux/musllinux container testing coverage
These additions are proposed to get feedback on which jobs should be kept
to maintain appropriate test coverage without the experimental 3.13t builds.
* ci: run in free-threading mode a bit more on 3.14
* Revert "ci: run in free-threading mode a bit more on 3.14"
This reverts commit 91189c9242e787922d26ca467710dcc494871b82.
Reason: https://github.com/pybind/pybind11/pull/5971#issuecomment-3831321903
* Reapply "ci: run in free-threading mode a bit more on 3.14"
This reverts commit f3197de97557a86a9a73df7890be1c227a7c4c59.
After #5972 is/was merged, tests should pass (already tested under #5980).
See also https://github.com/pybind/pybind11/pull/5972#discussion_r2752674989
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com>
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
Co-authored-by: Ralf W. Grosse-Kunstleve <rwgkio@gmail.com>
3 files changed