From f2c0ab83bcfd39600797d5fe24516db7bc73af3c Mon Sep 17 00:00:00 2001 From: b-pass Date: Tue, 17 Jun 2025 23:50:30 -0400 Subject: [PATCH] Fix TSan warning in sub-interpreter test (#5729) --- include/pybind11/detail/internals.h | 7 +++++-- tests/test_embed/test_subinterpreter.cpp | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index 414ab897e..ad2ff74cb 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -521,8 +521,11 @@ public: /// Drop all the references we're currently holding. void unref() { #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT - last_istate_.reset(); - internals_tls_p_.reset(); + if (get_num_interpreters_seen() > 1) { + last_istate_.reset(); + internals_tls_p_.reset(); + return; + } #endif internals_singleton_pp_ = nullptr; } diff --git a/tests/test_embed/test_subinterpreter.cpp b/tests/test_embed/test_subinterpreter.cpp index d31439438..3c7c35be1 100644 --- a/tests/test_embed/test_subinterpreter.cpp +++ b/tests/test_embed/test_subinterpreter.cpp @@ -20,11 +20,21 @@ bool has_state_dict_internals_obj(); uintptr_t get_details_as_uintptr(); void unsafe_reset_internals_for_single_interpreter() { - // unsafe normally, but for subsequent tests, put this back.. we know there are no threads - // running and only 1 interpreter + // NOTE: This code is NOT SAFE unless the caller guarantees no other threads are alive + // NOTE: This code is tied to the precise implementation of the internals holder + + // first, unref the thread local internals py::detail::get_internals_pp_manager().unref(); py::detail::get_local_internals_pp_manager().unref(); + + // we know there are no other interpreters, so we can lower this. SUPER DANGEROUS py::detail::get_num_interpreters_seen() = 1; + + // now we unref the static global singleton internals + py::detail::get_internals_pp_manager().unref(); + py::detail::get_local_internals_pp_manager().unref(); + + // finally, we reload the static global singleton py::detail::get_internals(); py::detail::get_local_internals(); }