From 450adb134d6fa4fadf750b03a7c9aa59c410a849 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 23 Oct 2026 20:34:36 +0200 Subject: [PATCH] Set the raised exception directly in _PyErr_SetObject() By the end of _PyErr_SetObject() the value is a normalized exception instance, so handing it to _PyErr_Restore() only created a reference to its type that was dropped again, and fetched the traceback of the value to set it back on the same object. Call _PyErr_SetRaisedException() directly instead. On the free-threaded build this also removes two atomic operations on the shared refcount of a heap exception type for every raise from a thread that does not own the type object. Co-Authored-By: Claude Fable 5.1 --- Python/errors.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Python/errors.c b/Python/errors.c index 0645c688a9af7ed..74fd2f0502f69c6 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -154,7 +154,6 @@ void _PyErr_SetObject(PyThreadState *tstate, PyObject *exception, PyObject *value) { PyObject *exc_value; - PyObject *tb = NULL; if (exception != NULL && !PyExceptionClass_Check(exception)) { @@ -237,9 +236,8 @@ _PyErr_SetObject(PyThreadState *tstate, PyObject *exception, PyObject *value) } } assert(value != NULL); - if (PyExceptionInstance_Check(value)) - tb = PyException_GetTraceback(value); - _PyErr_Restore(tstate, Py_NewRef(Py_TYPE(value)), value, tb); + assert(PyExceptionInstance_Check(value)); + _PyErr_SetRaisedException(tstate, value); } void