diff options
author | Irit Katriel <1055913+iritkatriel@users.noreply.github.com> | 2021-11-30 22:37:04 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-30 22:37:04 (GMT) |
commit | 8a45ca542a65ea27e7acaa44a4c833a27830e796 (patch) | |
tree | 8cc5563159c3c11b88d0f9c9b9164ed21a9d9e7f /Python/errors.c | |
parent | af8c8caaf5e07c02202d736a31f6a2f7e27819b8 (diff) | |
download | cpython-8a45ca542a65ea27e7acaa44a4c833a27830e796.zip cpython-8a45ca542a65ea27e7acaa44a4c833a27830e796.tar.gz cpython-8a45ca542a65ea27e7acaa44a4c833a27830e796.tar.bz2 |
bpo-45711: Change exc_info related APIs to derive type and traceback from the exception instance (GH-29780)
Diffstat (limited to 'Python/errors.c')
-rw-r--r-- | Python/errors.c | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/Python/errors.c b/Python/errors.c index 6e74d19..0a8b5a2 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -470,6 +470,33 @@ PyErr_Clear(void) _PyErr_Clear(tstate); } +static PyObject* +get_exc_type(PyObject *exc_value) /* returns a borrowed ref */ +{ + if (exc_value == NULL || exc_value == Py_None) { + return Py_None; + } + else { + assert(PyExceptionInstance_Check(exc_value)); + PyObject *type = PyExceptionInstance_Class(exc_value); + assert(type != NULL); + return type; + } +} + +static PyObject* +get_exc_traceback(PyObject *exc_value) /* returns a borrowed ref */ +{ + if (exc_value == NULL || exc_value == Py_None) { + return Py_None; + } + else { + assert(PyExceptionInstance_Check(exc_value)); + PyObject *tb = PyException_GetTraceback(exc_value); + Py_XDECREF(tb); + return tb ? tb : Py_None; + } +} void _PyErr_GetExcInfo(PyThreadState *tstate, @@ -477,18 +504,9 @@ _PyErr_GetExcInfo(PyThreadState *tstate, { _PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate); + *p_type = get_exc_type(exc_info->exc_value); *p_value = exc_info->exc_value; - *p_traceback = exc_info->exc_traceback; - - if (*p_value == NULL || *p_value == Py_None) { - assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None); - *p_type = Py_None; - } - else { - assert(PyExceptionInstance_Check(*p_value)); - assert(exc_info->exc_type == PyExceptionInstance_Class(*p_value)); - *p_type = PyExceptionInstance_Class(*p_value); - } + *p_traceback = get_exc_traceback(exc_info->exc_value); Py_XINCREF(*p_type); Py_XINCREF(*p_value); @@ -504,7 +522,7 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) } void -PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback) +PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) { PyObject *oldtype, *oldvalue, *oldtraceback; PyThreadState *tstate = _PyThreadState_GET(); @@ -513,9 +531,16 @@ PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback) oldvalue = tstate->exc_info->exc_value; oldtraceback = tstate->exc_info->exc_traceback; - tstate->exc_info->exc_type = p_type; - tstate->exc_info->exc_value = p_value; - tstate->exc_info->exc_traceback = p_traceback; + + tstate->exc_info->exc_type = get_exc_type(value); + Py_XINCREF(tstate->exc_info->exc_type); + tstate->exc_info->exc_value = value; + tstate->exc_info->exc_traceback = get_exc_traceback(value); + Py_XINCREF(tstate->exc_info->exc_traceback); + + /* These args are no longer used, but we still need to steal a ref */ + Py_XDECREF(type); + Py_XDECREF(traceback); Py_XDECREF(oldtype); Py_XDECREF(oldvalue); @@ -527,22 +552,19 @@ PyObject* _PyErr_StackItemToExcInfoTuple(_PyErr_StackItem *err_info) { PyObject *exc_value = err_info->exc_value; - if (exc_value == NULL) { - exc_value = Py_None; - } - assert(exc_value == Py_None || PyExceptionInstance_Check(exc_value)); + assert(exc_value == NULL || + exc_value == Py_None || + PyExceptionInstance_Check(exc_value)); - PyObject *exc_type = PyExceptionInstance_Check(exc_value) ? - PyExceptionInstance_Class(exc_value) : - Py_None; + PyObject *exc_type = get_exc_type(exc_value); + PyObject *exc_traceback = get_exc_traceback(exc_value); return Py_BuildValue( "(OOO)", - exc_type, - exc_value, - err_info->exc_traceback != NULL ? - err_info->exc_traceback : Py_None); + exc_type ? exc_type : Py_None, + exc_value ? exc_value : Py_None, + exc_traceback ? exc_traceback : Py_None); } |