@@ -143,6 +143,16 @@ inline PyTypeObject *make_default_metaclass();
143143inline PyObject *make_object_base_type (PyTypeObject *metaclass);
144144inline void translate_exception (std::exception_ptr p);
145145
146+ inline PyThreadState *get_thread_state_unchecked () {
147+ #if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
148+ return PyThreadState_GET ();
149+ #elif PY_VERSION_HEX < 0x030D0000
150+ return _PyThreadState_UncheckedGet ();
151+ #else
152+ return PyThreadState_GetUnchecked ();
153+ #endif
154+ }
155+
146156// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
147157// other STLs, this means `typeid(A)` from one module won't equal `typeid(A)` from another module
148158// even when `A` is the same, non-hidden-visibility type (e.g. from a common include). Under
@@ -195,14 +205,6 @@ struct override_hash {
195205
196206using instance_map = std::unordered_multimap<const void *, instance *>;
197207
198- inline bool is_interpreter_alive () {
199- #if PY_VERSION_HEX < 0x030D0000
200- return Py_IsInitialized () != 0 || _Py_IsFinalizing () != 0 ;
201- #else
202- return Py_IsInitialized () != 0 || Py_IsFinalizing () != 0 ;
203- #endif
204- }
205-
206208#ifdef Py_GIL_DISABLED
207209// Wrapper around PyMutex to provide BasicLockable semantics
208210class pymutex {
@@ -295,9 +297,7 @@ struct internals {
295297 : static_property_type(make_static_property_type()),
296298 default_metaclass (make_default_metaclass()) {
297299 tstate.set (nullptr ); // See PR #5870
298- PyThreadState *cur_tstate = PyThreadState_Get ();
299-
300- istate = cur_tstate->interp ;
300+ istate = PyInterpreterState_Get ();
301301 registered_exception_translators.push_front (&translate_exception);
302302#ifdef Py_GIL_DISABLED
303303 // Scale proportional to the number of cores. 2x is a heuristic to reduce contention.
@@ -320,8 +320,10 @@ struct internals {
320320 // Normally this destructor runs during interpreter finalization and it may DECREF things.
321321 // In odd finalization scenarios it might end up running after the interpreter has
322322 // completely shut down, In that case, we should not decref these objects because pymalloc
323- // is gone.
324- if (is_interpreter_alive ()) {
323+ // is gone. This also applies across sub-interpreters, we should only DECREF when the
324+ // original owning interpreter is active.
325+ auto *tstate = get_thread_state_unchecked ();
326+ if (tstate && tstate->interp == istate) {
325327 Py_CLEAR (instance_base);
326328 Py_CLEAR (default_metaclass);
327329 Py_CLEAR (static_property_type);
@@ -336,20 +338,25 @@ struct internals {
336338// impact any other modules, because the only things accessing the local internals is the
337339// module that contains them.
338340struct local_internals {
341+ local_internals () : istate(PyInterpreterState_Get()) {}
342+
339343 // It should be safe to use fast_type_map here because this entire
340344 // data structure is scoped to our single module, and thus a single
341345 // DSO and single instance of type_info for any particular type.
342346 fast_type_map<type_info *> registered_types_cpp;
343347
344348 std::forward_list<ExceptionTranslator> registered_exception_translators;
345349 PyTypeObject *function_record_py_type = nullptr ;
350+ PyInterpreterState *istate = nullptr ;
346351
347352 ~local_internals () {
348353 // Normally this destructor runs during interpreter finalization and it may DECREF things.
349354 // In odd finalization scenarios it might end up running after the interpreter has
350355 // completely shut down, In that case, we should not decref these objects because pymalloc
351- // is gone.
352- if (is_interpreter_alive ()) {
356+ // is gone. This also applies across sub-interpreters, we should only DECREF when the
357+ // original owning interpreter is active.
358+ auto *tstate = get_thread_state_unchecked ();
359+ if (tstate && tstate->interp == istate) {
353360 Py_CLEAR (function_record_py_type);
354361 }
355362 }
@@ -436,16 +443,6 @@ struct native_enum_record {
436443 " __pybind11_module_local_v" PYBIND11_TOSTRING (PYBIND11_INTERNALS_VERSION ) \
437444 PYBIND11_COMPILER_TYPE_LEADING_UNDERSCORE PYBIND11_PLATFORM_ABI_ID " __"
438445
439- inline PyThreadState *get_thread_state_unchecked () {
440- #if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
441- return PyThreadState_GET ();
442- #elif PY_VERSION_HEX < 0x030D0000
443- return _PyThreadState_UncheckedGet ();
444- #else
445- return PyThreadState_GetUnchecked ();
446- #endif
447- }
448-
449446// / We use this to figure out if there are or have been multiple subinterpreters active at any
450447// / point. This must never go from true to false while any interpreter may be running in any
451448// / thread!
0 commit comments