If a task object is still alive at interpreter teardown, something can try to print it. This will end in _asyncio.Future._repr_info that in turn calls:
return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
but asyncio_future_repr_info_func at that point can be NULL because module_free of _asynciomodule.c has been executed already, called by Py_FinalizeEx -> finalize_modules -> _PyInterpreterState_ClearModules -> ... -> module_dealloc.
The crash happens in the last _PyGC_CollectNoFail of finalize_modules so somehow the task survived the first collection and then was garbage in the second one.
I don;t have a simple repro for now, but you can get the failure by cloning https://github.com/Textualize/textual checking commit 5fe47da058564b72e5081a5658c054f55a5d85cd, installing the project and test deps and running pytest.
If a task object is still alive at interpreter teardown, something can try to print it. This will end in
_asyncio.Future._repr_infothat in turn calls:but
asyncio_future_repr_info_funcat that point can beNULLbecausemodule_freeof_asynciomodule.chas been executed already, called byPy_FinalizeEx -> finalize_modules -> _PyInterpreterState_ClearModules -> ... -> module_dealloc.The crash happens in the last
_PyGC_CollectNoFailoffinalize_modulesso somehow the task survived the first collection and then was garbage in the second one.I don;t have a simple repro for now, but you can get the failure by cloning https://github.com/Textualize/textual checking commit 5fe47da058564b72e5081a5658c054f55a5d85cd, installing the project and test deps and running
pytest.