@@ -355,19 +355,7 @@ struct internals {
355355 internals (internals &&other) = delete;
356356 internals &operator =(const internals &other) = delete ;
357357 internals &operator =(internals &&other) = delete ;
358- ~internals () {
359- // Normally this destructor runs during interpreter finalization and it may DECREF things.
360- // In odd finalization scenarios it might end up running after the interpreter has
361- // completely shut down, In that case, we should not decref these objects because pymalloc
362- // is gone. This also applies across sub-interpreters, we should only DECREF when the
363- // original owning interpreter is active.
364- auto *cur_istate = get_interpreter_state_unchecked ();
365- if (cur_istate && cur_istate == istate) {
366- Py_CLEAR (instance_base);
367- Py_CLEAR (default_metaclass);
368- Py_CLEAR (static_property_type);
369- }
370- }
358+ ~internals () = default ;
371359};
372360
373361// the internals struct (above) is shared between all the modules. local_internals are only
@@ -377,28 +365,13 @@ struct internals {
377365// impact any other modules, because the only things accessing the local internals is the
378366// module that contains them.
379367struct local_internals {
380- local_internals () : istate(get_interpreter_state_unchecked()) {}
381-
382368 // It should be safe to use fast_type_map here because this entire
383369 // data structure is scoped to our single module, and thus a single
384370 // DSO and single instance of type_info for any particular type.
385371 fast_type_map<type_info *> registered_types_cpp;
386372
387373 std::forward_list<ExceptionTranslator> registered_exception_translators;
388374 PyTypeObject *function_record_py_type = nullptr ;
389- PyInterpreterState *istate = nullptr ;
390-
391- ~local_internals () {
392- // Normally this destructor runs during interpreter finalization and it may DECREF things.
393- // In odd finalization scenarios it might end up running after the interpreter has
394- // completely shut down, In that case, we should not decref these objects because pymalloc
395- // is gone. This also applies across sub-interpreters, we should only DECREF when the
396- // original owning interpreter is active.
397- auto *cur_istate = get_interpreter_state_unchecked ();
398- if (cur_istate && cur_istate == istate) {
399- Py_CLEAR (function_record_py_type);
400- }
401- }
402375};
403376
404377enum class holder_enum_t : uint8_t {
@@ -594,6 +567,10 @@ inline void translate_local_exception(std::exception_ptr p) {
594567}
595568#endif
596569
570+ // Sentinel value for the `dtor` parameter of `atomic_get_or_create_in_state_dict`.
571+ // Indicates no destructor was explicitly provided (distinct from nullptr, which means "leak").
572+ #define PYBIND11_DTOR_USE_DELETE (reinterpret_cast <void (*)(PyObject *)>(1 ))
573+
597574// Get or create per-storage capsule in the current interpreter's state dict.
598575// - The storage is interpreter-dependent: different interpreters will have different storage.
599576// This is important when using multiple-interpreters, to avoid sharing unshareable objects
@@ -610,9 +587,14 @@ inline void translate_local_exception(std::exception_ptr p) {
610587//
611588// Returns: pair of (pointer to storage, bool indicating if newly created).
612589// The bool follows std::map::insert convention: true = created, false = existed.
590+ // `dtor`: optional destructor called when the interpreter shuts down.
591+ // - If not provided: the storage will be deleted using `delete`.
592+ // - If nullptr: the storage will be leaked (useful for singletons that outlive the interpreter).
593+ // - If a function: that function will be called with the capsule object.
613594template <typename Payload>
614595std::pair<Payload *, bool > atomic_get_or_create_in_state_dict (const char *key,
615- void (*dtor)(PyObject *) = nullptr) {
596+ void (*dtor)(PyObject *)
597+ = PYBIND11_DTOR_USE_DELETE) {
616598 error_scope err_scope; // preserve any existing Python error states
617599
618600 auto state_dict = reinterpret_borrow<dict>(get_python_state_dict ());
@@ -658,7 +640,7 @@ std::pair<Payload *, bool> atomic_get_or_create_in_state_dict(const char *key,
658640 // - Otherwise, our `new_capsule` is now in the dict, and it owns the storage and the state
659641 // dict will incref it. We need to set the caller's destructor on it, which will be
660642 // called when the interpreter shuts down.
661- if (created && dtor) {
643+ if (created && dtor != PYBIND11_DTOR_USE_DELETE ) {
662644 if (PyCapsule_SetDestructor (capsule_obj, dtor) < 0 ) {
663645 throw error_already_set ();
664646 }
@@ -675,6 +657,8 @@ std::pair<Payload *, bool> atomic_get_or_create_in_state_dict(const char *key,
675657 return std::pair<Payload *, bool >(static_cast <Payload *>(raw_ptr), created);
676658}
677659
660+ #undef PYBIND11_DTOR_USE_DELETE
661+
678662template <typename InternalsType>
679663class internals_pp_manager {
680664public:
@@ -731,42 +715,75 @@ class internals_pp_manager {
731715 // this could be called without an active interpreter, just use what was cached
732716 if (!tstate || tstate->interp == last_istate_tls ()) {
733717 auto tpp = internals_p_tls ();
734-
735- delete tpp;
718+ {
719+ std::lock_guard<std::mutex> lock (pp_set_mutex_);
720+ pps_have_created_content_.erase (tpp); // untrack deleted pp
721+ }
722+ delete tpp; // may call back into Python
736723 }
737724 unref ();
738725 return ;
739726 }
740727#endif
741- delete internals_singleton_pp_;
728+ {
729+ std::lock_guard<std::mutex> lock (pp_set_mutex_);
730+ pps_have_created_content_.erase (internals_singleton_pp_); // untrack deleted pp
731+ }
732+ delete internals_singleton_pp_; // may call back into Python
742733 unref ();
743734 }
744735
745- private:
746- internals_pp_manager (char const *id, on_fetch_function *on_fetch)
747- : holder_id_(id), on_fetch_(on_fetch) {}
736+ void create_pp_content_once (std::unique_ptr<InternalsType> *const pp) {
737+ // Assume the GIL is held here. May call back into Python. We cannot hold the lock with our
738+ // mutex here. So there may be multiple threads creating the content at the same time. Only
739+ // one will install its content to pp below. Others will be freed when going out of scope.
740+ auto tmp = std::unique_ptr<InternalsType>(new InternalsType ());
748741
749- static void internals_shutdown (PyObject *capsule) {
750- auto *pp = static_cast <std::unique_ptr<InternalsType> *>(
751- PyCapsule_GetPointer (capsule, nullptr ));
752- if (pp) {
753- pp->reset ();
742+ {
743+ // Lock scope must not include Python calls, which may require the GIL and cause
744+ // deadlocks.
745+ std::lock_guard<std::mutex> lock (pp_set_mutex_);
746+
747+ if (*pp) {
748+ // Already created in another thread.
749+ return ;
750+ }
751+
752+ // At this point, pp->get() is nullptr.
753+ // The content is either not yet created, or was previously destroyed via pp->reset().
754+
755+ // Detect re-creation of internals after destruction during interpreter shutdown.
756+ // If pybind11 code (e.g., tp_traverse/tp_clear calling py::cast) runs after internals
757+ // have been destroyed, a new empty internals would be created, causing type lookup
758+ // failures. See also get_or_create_pp_in_state_dict() comments.
759+ if (pps_have_created_content_.find (pp) != pps_have_created_content_.end ()) {
760+ pybind11_fail (
761+ " pybind11::detail::internals_pp_manager::create_pp_content_once() "
762+ " FAILED: reentrant call detected while fetching pybind11 internals!" );
763+ }
764+
765+ // Each interpreter can only create its internals once.
766+ pps_have_created_content_.insert (pp);
767+ // Install the created content.
768+ pp->swap (tmp);
754769 }
755- // We reset the unique_ptr's contents but cannot delete the unique_ptr itself here.
756- // The pp_manager in this module (and possibly other modules sharing internals) holds
757- // a raw pointer to this unique_ptr, and that pointer would dangle if we deleted it now.
758- //
759- // For pybind11-owned interpreters (via embed.h or subinterpreter.h), destroy() is
760- // called after Py_Finalize/Py_EndInterpreter completes, which safely deletes the
761- // unique_ptr. For interpreters not owned by pybind11 (e.g., a pybind11 extension
762- // loaded into an external interpreter), destroy() is never called and the unique_ptr
763- // shell (8 bytes, not its contents) is leaked.
764- // (See PR #5958 for ideas to eliminate this leak.)
765770 }
766771
772+ private:
773+ internals_pp_manager (char const *id, on_fetch_function *on_fetch)
774+ : holder_id_(id), on_fetch_(on_fetch) {}
775+
767776 std::unique_ptr<InternalsType> *get_or_create_pp_in_state_dict () {
777+ // The `unique_ptr<InternalsType>` is intentionally leaked on interpreter shutdown.
778+ // Once an instance is created, it will never be deleted until the process exits (compare
779+ // to interpreter shutdown in multiple-interpreter scenarios).
780+ // We cannot guarantee the destruction order of capsules in the interpreter state dict on
781+ // interpreter shutdown, so deleting internals too early could cause undefined behavior
782+ // when other pybind11 objects access `get_internals()` during finalization (which would
783+ // recreate empty internals). See also create_pp_content_once() above.
784+ // See https://github.com/pybind/pybind11/pull/5958#discussion_r2717645230.
768785 auto result = atomic_get_or_create_in_state_dict<std::unique_ptr<InternalsType>>(
769- holder_id_, &internals_shutdown );
786+ holder_id_, /* dtor= */ nullptr /* leak the capsule content */ );
770787 auto *pp = result.first ;
771788 bool created = result.second ;
772789 // Only call on_fetch_ when fetching existing internals, not when creating new ones.
@@ -792,7 +809,12 @@ class internals_pp_manager {
792809 on_fetch_function *on_fetch_ = nullptr ;
793810 // Pointer-to-pointer to the singleton internals for the first seen interpreter (may not be the
794811 // main interpreter)
795- std::unique_ptr<InternalsType> *internals_singleton_pp_;
812+ std::unique_ptr<InternalsType> *internals_singleton_pp_ = nullptr ;
813+
814+ // Track pointer-to-pointers whose internals have been created, to detect re-entrancy.
815+ // Use instance member over static due to singleton pattern of this class.
816+ std::unordered_set<std::unique_ptr<InternalsType> *> pps_have_created_content_;
817+ std::mutex pp_set_mutex_;
796818};
797819
798820// If We loaded the internals through `state_dict`, our `error_already_set`
@@ -833,7 +855,8 @@ PYBIND11_NOINLINE internals &get_internals() {
833855 // Slow path, something needs fetched from the state dict or created
834856 gil_scoped_acquire_simple gil;
835857 error_scope err_scope;
836- internals_ptr.reset (new internals ());
858+
859+ ppmgr.create_pp_content_once (&internals_ptr);
837860
838861 if (!internals_ptr->instance_base ) {
839862 // This calls get_internals, so cannot be called from within the internals constructor
@@ -844,6 +867,31 @@ PYBIND11_NOINLINE internals &get_internals() {
844867 return *internals_ptr;
845868}
846869
870+ // / Return the PyObject* for the internals capsule (borrowed reference).
871+ // / Returns nullptr if the capsule doesn't exist yet.
872+ inline PyObject *get_internals_capsule () {
873+ auto state_dict = reinterpret_borrow<dict>(get_python_state_dict ());
874+ return dict_getitemstring (state_dict.ptr (), PYBIND11_INTERNALS_ID);
875+ }
876+
877+ // / Return the key used for local_internals in the state dict.
878+ // / This function ensures a consistent key is used across all call sites within the same
879+ // / compilation unit. The key includes the address of a static variable to make it unique per
880+ // / module (DSO), matching the behavior of get_local_internals_pp_manager().
881+ inline const std::string &get_local_internals_key () {
882+ static const std::string key
883+ = PYBIND11_MODULE_LOCAL_ID + std::to_string (reinterpret_cast <uintptr_t >(&key));
884+ return key;
885+ }
886+
887+ // / Return the PyObject* for the local_internals capsule (borrowed reference).
888+ // / Returns nullptr if the capsule doesn't exist yet.
889+ inline PyObject *get_local_internals_capsule () {
890+ const auto &key = get_local_internals_key ();
891+ auto state_dict = reinterpret_borrow<dict>(get_python_state_dict ());
892+ return dict_getitemstring (state_dict.ptr (), key.c_str ());
893+ }
894+
847895inline void ensure_internals () {
848896 pybind11::detail::get_internals_pp_manager ().unref ();
849897#ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT
@@ -855,20 +903,21 @@ inline void ensure_internals() {
855903}
856904
857905inline internals_pp_manager<local_internals> &get_local_internals_pp_manager () {
858- // Use the address of this static itself as part of the key, so that the value is uniquely tied
906+ // Use the address of a static variable as part of the key, so that the value is uniquely tied
859907 // to where the module is loaded in memory
860- static const std::string this_module_idstr
861- = PYBIND11_MODULE_LOCAL_ID
862- + std::to_string (reinterpret_cast <uintptr_t >(&this_module_idstr));
863- return internals_pp_manager<local_internals>::get_instance (this_module_idstr.c_str (), nullptr );
908+ return internals_pp_manager<local_internals>::get_instance (get_local_internals_key ().c_str (),
909+ nullptr );
864910}
865911
866912// / Works like `get_internals`, but for things which are locally registered.
867913inline local_internals &get_local_internals () {
868914 auto &ppmgr = get_local_internals_pp_manager ();
869915 auto &internals_ptr = *ppmgr.get_pp ();
870916 if (!internals_ptr) {
871- internals_ptr.reset (new local_internals ());
917+ gil_scoped_acquire_simple gil;
918+ error_scope err_scope;
919+
920+ ppmgr.create_pp_content_once (&internals_ptr);
872921 }
873922 return *internals_ptr;
874923}
0 commit comments