Mercurial > cpython-lru_cache-weakref
diff Python/errors.c @ 48887:c562c8dae49a
Issue 3611: in some cases (a __del__ re-raising an exception, when called from inside
an 'except' clause), the exception __context__ would be reset to None.
This crases the interpreter if this precisely happens inside PyErr_SetObject.
- now the __context__ is properly preserved
- in any case, PyErr_SetObject now saves the current exc_value in a local variable, to
avoid such crashes in the future.
Reviewer: Antoine Pitrou.
| author | Amaury Forgeot d'Arc <amauryfa@gmail.com> |
|---|---|
| date | Fri, 29 Aug 2008 07:13:32 +0000 |
| parents | d6e86a96f9b3 |
| children | f221fce3d6ba |
line wrap: on
line diff
--- a/Python/errors.c Thu Aug 28 14:55:10 2008 +0000 +++ b/Python/errors.c Fri Aug 29 07:13:32 2008 +0000 @@ -53,6 +53,7 @@ PyErr_SetObject(PyObject *exception, PyObject *value) { PyThreadState *tstate = PyThreadState_GET(); + PyObject *exc_value; PyObject *tb = NULL; if (exception != NULL && @@ -63,8 +64,10 @@ return; } Py_XINCREF(value); - if (tstate->exc_value != NULL && tstate->exc_value != Py_None) { + exc_value = tstate->exc_value; + if (exc_value != NULL && exc_value != Py_None) { /* Implicit exception chaining */ + Py_INCREF(exc_value); if (value == NULL || !PyExceptionInstance_Check(value)) { /* We must normalize the value right now */ PyObject *args, *fixed_value; @@ -88,8 +91,8 @@ This is O(chain length) but context chains are usually very short. Sensitive readers may try to inline the call to PyException_GetContext. */ - if (tstate->exc_value != value) { - PyObject *o = tstate->exc_value, *context; + if (exc_value != value) { + PyObject *o = exc_value, *context; while ((context = PyException_GetContext(o))) { Py_DECREF(context); if (context == value) { @@ -98,8 +101,9 @@ } o = context; } - Py_INCREF(tstate->exc_value); - PyException_SetContext(value, tstate->exc_value); + PyException_SetContext(value, exc_value); + } else { + Py_DECREF(exc_value); } } if (value != NULL && PyExceptionInstance_Check(value))
