You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: 3.10 debug build crashes on interpreter exit #32509
I'm building a full debug Python environment (Python 3.12.4, numpy 2.4.6, pybind 3.1, contourpy 1.3.3, MPL 3.10.9)
It seems that when MPL has been imported, the python interpreter shutdown will show a GIL error:
Fatal Python error: _PyInterpreterState_GET: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is released (the current Python thread state is NULL)
Python runtime state: finalizing (tstate=0x00007ffbe152fca0)
In release builds, this does not occur, but I suppose it's because there are less asserts on GIL state at shutdown.
When debugging, the stack is
KernelBase.dll!00007ff843eb3122() Unknown
python312_d.dll!fatal_error_exit(int status) Line 2778 C
python312_d.dll!fatal_error(int fd, int header, const char * prefix, const char * msg, int status) Line 2959 C
python312_d.dll!_Py_FatalErrorFunc(const char * func, const char * msg) Line 2975 C
python312_d.dll!_PyInterpreterState_GET() Line 131 C
python312_d.dll!_Py_DECREF_DecRefTotal() Line 240 C
ft2font_d.cp312-win_amd64.pyd!Py_DECREF(const char * filename, int lineno, _object * op) Line 688 C++
ft2font_d.cp312-win_amd64.pyd!Py_XDECREF(_object * op) Line 798 C++
ft2font_d.cp312-win_amd64.pyd!pybind11::handle::dec_ref() Line 300 C++
ft2font_d.cp312-win_amd64.pyd!pybind11::object::~object() Line 395 C++
ft2font_d.cp312-win_amd64.pyd!std::pair<std::string const ,pybind11::object>::~pair<std::string const ,pybind11::object>() C++
ft2font_d.cp312-win_amd64.pyd!std::pair<std::string const ,pybind11::object>::`scalar deleting destructor'(unsigned int) C++
ft2font_d.cp312-win_amd64.pyd!std::_Default_allocator_traits<std::allocator<std::_List_node<std::pair<std::string const ,pybind11::object>,void *>>>::destroy<std::pair<std::string const ,pybind11::object>>(std::allocator<std::_List_node<std::pair<std::string const ,pybind11::object>,void *>> & __formal, std::pair<std::string const ,pybind11::object> * const _Ptr) Line 741 C++
ft2font_d.cp312-win_amd64.pyd!std::_List_node<std::pair<std::string const ,pybind11::object>,void *>::_Freenode<std::allocator<std::_List_node<std::pair<std::string const ,pybind11::object>,void *>>>(std::allocator<std::_List_node<std::pair<std::string const ,pybind11::object>,void *>> & _Al, std::_List_node<std::pair<std::string const ,pybind11::object>,void *> * _Ptr) Line 318 C++
ft2font_d.cp312-win_amd64.pyd!std::_List_node<std::pair<std::string const ,pybind11::object>,void *>::_Free_non_head<std::allocator<std::_List_node<std::pair<std::string const ,pybind11::object>,void *>>>(std::allocator<std::_List_node<std::pair<std::string const ,pybind11::object>,void *>> & _Al, std::_List_node<std::pair<std::string const ,pybind11::object>,void *> * _Head) Line 329 C++
ft2font_d.cp312-win_amd64.pyd!std::list<std::pair<std::string const ,pybind11::object>,std::allocator<std::pair<std::string const ,pybind11::object>>>::_Tidy() Line 1519 C++
ft2font_d.cp312-win_amd64.pyd!std::list<std::pair<std::string const ,pybind11::object>,std::allocator<std::pair<std::string const ,pybind11::object>>>::~list<std::pair<std::string const ,pybind11::object>,std::allocator<std::pair<std::string const ,pybind11::object>>>() Line 1063 C++
ft2font_d.cp312-win_amd64.pyd!std::_Hash<std::_Umap_traits<std::string,pybind11::object,std::_Uhash_compare<std::string,std::hash<std::string>,std::equal_to<std::string>>,std::allocator<std::pair<std::string const ,pybind11::object>>,0>>::~_Hash<std::_Umap_traits<std::string,pybind11::object,std::_Uhash_compare<std::string,std::hash<std::string>,std::equal_to<std::string>>,std::allocator<std::pair<std::string const ,pybind11::object>>,0>>() C++
ft2font_d.cp312-win_amd64.pyd!std::unordered_map<std::string,pybind11::object,std::hash<std::string>,std::equal_to<std::string>,std::allocator<std::pair<std::string const ,pybind11::object>>>::~unordered_map<std::string,pybind11::object,std::hash<std::string>,std::equal_to<std::string>,std::allocator<std::pair<std::string const ,pybind11::object>>>() C++
ft2font_d.cp312-win_amd64.pyd!p11x::`anonymous namespace'::`dynamic atexit destructor for 'enums''() C++
ucrtbased.dll!00007fff08e62b99() Unknown
ucrtbased.dll!00007fff08e625c5() Unknown
ucrtbased.dll!00007fff08e62717() Unknown
ucrtbased.dll!00007fff08e62d44() Unknown
ft2font_d.cp312-win_amd64.pyd!__scrt_dllmain_uninitialize_c() Line 398 C++
> ft2font_d.cp312-win_amd64.pyd!dllmain_crt_process_detach(const bool is_terminating) Line 182 C++
ft2font_d.cp312-win_amd64.pyd!dllmain_crt_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 220 C++
ft2font_d.cp312-win_amd64.pyd!dllmain_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 293 C++
ft2font_d.cp312-win_amd64.pyd!_DllMainCRTStartup(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 335 C++
ntdll.dll!00007ff84667ef6a() Unknown
ntdll.dll!00007ff84657b2e3() Unknown
ntdll.dll!00007ff8465e027f() Unknown
ntdll.dll!00007ff8465def8e() Unknown
kernel32.dll!00007ff8447a17ab() Unknown
ucrtbased.dll!00007fff08e6219b() Unknown
ucrtbased.dll!00007fff08e6214f() Unknown
ucrtbased.dll!00007fff08e62456() Unknown
python_d.exe!__scrt_common_main_seh() Line 295 C++
python_d.exe!__scrt_common_main() Line 331 C++
python_d.exe!wmainCRTStartup(void * __formal) Line 17 C++
kernel32.dll!00007ff84478dda7() Unknown
ntdll.dll!00007ff8465dee4c() Unknown
It seems the enums map is deleted in scalar destructor at exit, far too late for python, and the decref crashes because of it.
As a workaround, since the object is not properly deleted anyways,
you can replace the line of _enums.h: auto enums = std::unordered_map<std::string, py::object>{};
by auto& enums = *new std::unordered_map<std::string, py::object>{};
So no delete attempt is done, and the problem disappears
Code changed in 3.11, so i suppose this only affects 3.10.x
Code for reproduction
python_d-c"import matplotlib"
Actual outcome
Fatal Python error: _PyInterpreterState_GET: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is released (the current Python thread state is NULL)
Python runtime state: finalizing (tstate=0x00007ffbe152fca0)
Expected outcome
Process imports matplotlib and finished without a GIL error
Activity
iccir commentedon Oct 20, 2026
Realistically, I don't think that this will be fixed for 3.10 unless it is a security issue.