Mercurial > cpython-lru_cache-weakref
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 48886:6ceb7c89e776 | 48887:c562c8dae49a |
|---|---|
| 51 | 51 |
| 52 void | 52 void |
| 53 PyErr_SetObject(PyObject *exception, PyObject *value) | 53 PyErr_SetObject(PyObject *exception, PyObject *value) |
| 54 { | 54 { |
| 55 PyThreadState *tstate = PyThreadState_GET(); | 55 PyThreadState *tstate = PyThreadState_GET(); |
| 56 PyObject *exc_value; | |
| 56 PyObject *tb = NULL; | 57 PyObject *tb = NULL; |
| 57 | 58 |
| 58 if (exception != NULL && | 59 if (exception != NULL && |
| 59 !PyExceptionClass_Check(exception)) { | 60 !PyExceptionClass_Check(exception)) { |
| 60 PyErr_Format(PyExc_SystemError, | 61 PyErr_Format(PyExc_SystemError, |
| 61 "exception %R not a BaseException subclass", | 62 "exception %R not a BaseException subclass", |
| 62 exception); | 63 exception); |
| 63 return; | 64 return; |
| 64 } | 65 } |
| 65 Py_XINCREF(value); | 66 Py_XINCREF(value); |
| 66 if (tstate->exc_value != NULL && tstate->exc_value != Py_None) { | 67 exc_value = tstate->exc_value; |
| 68 if (exc_value != NULL && exc_value != Py_None) { | |
| 67 /* Implicit exception chaining */ | 69 /* Implicit exception chaining */ |
| 70 Py_INCREF(exc_value); | |
| 68 if (value == NULL || !PyExceptionInstance_Check(value)) { | 71 if (value == NULL || !PyExceptionInstance_Check(value)) { |
| 69 /* We must normalize the value right now */ | 72 /* We must normalize the value right now */ |
| 70 PyObject *args, *fixed_value; | 73 PyObject *args, *fixed_value; |
| 71 if (value == NULL || value == Py_None) | 74 if (value == NULL || value == Py_None) |
| 72 args = PyTuple_New(0); | 75 args = PyTuple_New(0); |
| 86 } | 89 } |
| 87 /* Avoid reference cycles through the context chain. | 90 /* Avoid reference cycles through the context chain. |
| 88 This is O(chain length) but context chains are | 91 This is O(chain length) but context chains are |
| 89 usually very short. Sensitive readers may try | 92 usually very short. Sensitive readers may try |
| 90 to inline the call to PyException_GetContext. */ | 93 to inline the call to PyException_GetContext. */ |
| 91 if (tstate->exc_value != value) { | 94 if (exc_value != value) { |
| 92 PyObject *o = tstate->exc_value, *context; | 95 PyObject *o = exc_value, *context; |
| 93 while ((context = PyException_GetContext(o))) { | 96 while ((context = PyException_GetContext(o))) { |
| 94 Py_DECREF(context); | 97 Py_DECREF(context); |
| 95 if (context == value) { | 98 if (context == value) { |
| 96 PyException_SetContext(o, NULL); | 99 PyException_SetContext(o, NULL); |
| 97 break; | 100 break; |
| 98 } | 101 } |
| 99 o = context; | 102 o = context; |
| 100 } | 103 } |
| 101 Py_INCREF(tstate->exc_value); | 104 PyException_SetContext(value, exc_value); |
| 102 PyException_SetContext(value, tstate->exc_value); | 105 } else { |
| 106 Py_DECREF(exc_value); | |
| 103 } | 107 } |
| 104 } | 108 } |
| 105 if (value != NULL && PyExceptionInstance_Check(value)) | 109 if (value != NULL && PyExceptionInstance_Check(value)) |
| 106 tb = PyException_GetTraceback(value); | 110 tb = PyException_GetTraceback(value); |
| 107 Py_XINCREF(exception); | 111 Py_XINCREF(exception); |
