From 4312bd311e8e7b2cac1383e01540b9c0560ba5c0 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 22 Jan 2022 20:49:24 +0100 Subject: [PATCH 1/2] bpo-46417: Py_Finalize() clears static exceptioins The Py_Finalize() function now clears exceptions implemented as static types. Add _PyExc_FiniTypes() function, called by _PyExc_Fini(). --- Objects/exceptions.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index f8f727c673c023..0f93e083af6376 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -3536,13 +3536,36 @@ _PyExc_InitTypes(PyInterpreterState *interp) } +static void +_PyExc_FiniTypes(PyInterpreterState *interp) +{ + if (!_Py_IsMainInterpreter(interp)) { + return; + } + + for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) { + PyTypeObject *exc = static_exceptions[i].exc; + + // Cannot delete a type if it still has subclasses + if (exc->tp_subclasses != NULL) { + continue; + } + + _PyStaticType_Dealloc(exc); + } +} + + PyStatus _PyExc_InitGlobalObjects(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + if (preallocate_memerrors() < 0) { return _PyStatus_NO_MEMORY(); } - return _PyStatus_OK(); } @@ -3656,6 +3679,8 @@ _PyExc_Fini(PyInterpreterState *interp) struct _Py_exc_state *state = &interp->exc_state; free_preallocated_memerrors(state); Py_CLEAR(state->errnomap); + + _PyExc_FiniTypes(interp); } /* Helper to do the equivalent of "raise X from Y" in C, but always using From aeb0fcdb6ebfe59b9d36c706f290e9a094d030e8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 22 Jan 2022 22:09:21 +0100 Subject: [PATCH 2/2] Clear exceptions in the reverse order --- Objects/exceptions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 0f93e083af6376..6bf70e2b15c16d 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -3543,7 +3543,7 @@ _PyExc_FiniTypes(PyInterpreterState *interp) return; } - for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) { + for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) { PyTypeObject *exc = static_exceptions[i].exc; // Cannot delete a type if it still has subclasses