Fix data race when using shared variables (free threading) (#5494)

* Fix data race when using shared variables (free threading)

In the free threading build, there's a race between wrapper re-use and
wrapper deallocation. This can happen with a static variable accessed by
multiple threads.

Fixing this requires using some private CPython APIs: _Py_TryIncref and
_PyObject_SetMaybeWeakref. The implementations of these functions are
included until they're made available as public ("unstable") APIs.

Fixes #5489

* style: pre-commit fixes

* Avoid unused parameter

* Add missing return for default build

* Changes from review

* Assign result to local variable

* s/clang-tidy/ruff

* clang-tidy: static is redundant

* Use 'noqa: B018'

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Sam Gross
2025-01-16 14:13:21 -05:00
committed by GitHub
parent 945e251a6c
commit 15d9dae14b
4 changed files with 96 additions and 1 deletions

View File

@@ -28,6 +28,9 @@ struct IntStruct {
int value;
};
struct EmptyStruct {};
EmptyStruct SharedInstance;
} // namespace
TEST_SUBMODULE(thread, m) {
@@ -61,6 +64,9 @@ TEST_SUBMODULE(thread, m) {
},
py::call_guard<py::gil_scoped_release>());
py::class_<EmptyStruct>(m, "EmptyStruct")
.def_readonly_static("SharedInstance", &SharedInstance);
// NOTE: std::string_view also uses loader_life_support to ensure that
// the string contents remain alive, but that's a C++ 17 feature.
}