@@ -153,6 +153,28 @@ inline PyThreadState *get_thread_state_unchecked() {
153153#endif
154154}
155155
156+ inline PyInterpreterState *get_interpreter_state_unchecked () {
157+ auto tstate = get_thread_state_unchecked ();
158+ return tstate ? tstate->interp : nullptr ;
159+ }
160+
161+ inline object get_python_state_dict () {
162+ object state_dict;
163+ #if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
164+ state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins ());
165+ #else
166+ auto istate = get_interpreter_state_unchecked ();
167+ if (istate) {
168+ state_dict = reinterpret_borrow<object>(PyInterpreterState_GetDict (istate));
169+ }
170+ #endif
171+ if (!state_dict) {
172+ raise_from (PyExc_SystemError, " pybind11::detail::get_python_state_dict() FAILED" );
173+ throw error_already_set ();
174+ }
175+ return state_dict;
176+ }
177+
156178// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
157179// other STLs, this means `typeid(A)` from one module won't equal `typeid(A)` from another module
158180// even when `A` is the same, non-hidden-visibility type (e.g. from a common include). Under
@@ -295,9 +317,8 @@ struct internals {
295317
296318 internals ()
297319 : static_property_type(make_static_property_type()),
298- default_metaclass (make_default_metaclass()) {
320+ default_metaclass (make_default_metaclass()), istate(get_interpreter_state_unchecked()) {
299321 tstate.set (nullptr ); // See PR #5870
300- istate = PyInterpreterState_Get ();
301322 registered_exception_translators.push_front (&translate_exception);
302323#ifdef Py_GIL_DISABLED
303324 // Scale proportional to the number of cores. 2x is a heuristic to reduce contention.
@@ -322,8 +343,7 @@ struct internals {
322343 // completely shut down, In that case, we should not decref these objects because pymalloc
323344 // is gone. This also applies across sub-interpreters, we should only DECREF when the
324345 // original owning interpreter is active.
325- auto *tstate = get_thread_state_unchecked ();
326- if (tstate && tstate->interp == istate) {
346+ if (get_interpreter_state_unchecked () == istate) {
327347 Py_CLEAR (instance_base);
328348 Py_CLEAR (default_metaclass);
329349 Py_CLEAR (static_property_type);
@@ -338,7 +358,7 @@ struct internals {
338358// impact any other modules, because the only things accessing the local internals is the
339359// module that contains them.
340360struct local_internals {
341- local_internals () : istate(PyInterpreterState_Get ()) {}
361+ local_internals () : istate(get_interpreter_state_unchecked ()) {}
342362
343363 // It should be safe to use fast_type_map here because this entire
344364 // data structure is scoped to our single module, and thus a single
@@ -355,8 +375,7 @@ struct local_internals {
355375 // completely shut down, In that case, we should not decref these objects because pymalloc
356376 // is gone. This also applies across sub-interpreters, we should only DECREF when the
357377 // original owning interpreter is active.
358- auto *tstate = get_thread_state_unchecked ();
359- if (tstate && tstate->interp == istate) {
378+ if (get_interpreter_state_unchecked () == istate) {
360379 Py_CLEAR (function_record_py_type);
361380 }
362381 }
@@ -555,27 +574,6 @@ inline void translate_local_exception(std::exception_ptr p) {
555574}
556575#endif
557576
558- inline object get_python_state_dict () {
559- object state_dict;
560- #if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
561- state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins ());
562- #else
563- # if PY_VERSION_HEX < 0x03090000
564- PyInterpreterState *istate = _PyInterpreterState_Get ();
565- # else
566- PyInterpreterState *istate = PyInterpreterState_Get ();
567- # endif
568- if (istate) {
569- state_dict = reinterpret_borrow<object>(PyInterpreterState_GetDict (istate));
570- }
571- #endif
572- if (!state_dict) {
573- raise_from (PyExc_SystemError, " pybind11::detail::get_python_state_dict() FAILED" );
574- throw error_already_set ();
575- }
576- return state_dict;
577- }
578-
579577// Get or create per-storage capsule in the current interpreter's state dict.
580578// - The storage is interpreter-dependent: different interpreters will have different storage.
581579// This is important when using multiple-interpreters, to avoid sharing unshareable objects
0 commit comments