diff options
Diffstat (limited to 'Cython/Utility/Exceptions.c')
-rw-r--r-- | Cython/Utility/Exceptions.c | 187 |
1 files changed, 154 insertions, 33 deletions
diff --git a/Cython/Utility/Exceptions.c b/Cython/Utility/Exceptions.c index 87d3a5cdd..abf95afda 100644 --- a/Cython/Utility/Exceptions.c +++ b/Cython/Utility/Exceptions.c @@ -6,6 +6,49 @@ // __Pyx_GetException() +/////////////// AssertionsEnabled.init /////////////// +__Pyx_init_assertions_enabled(); + +/////////////// AssertionsEnabled.proto /////////////// + +#define __Pyx_init_assertions_enabled() + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define __pyx_assertions_enabled() (1) +#elif PY_VERSION_HEX < 0x03080000 || CYTHON_COMPILING_IN_PYPY || defined(Py_LIMITED_API) + #define __pyx_assertions_enabled() (!Py_OptimizeFlag) +#elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030900A6 + // Py3.8+ has PyConfig from PEP 587, but only Py3.9 added read access to it. + // Py_OptimizeFlag is deprecated in Py3.12+ + static int __pyx_assertions_enabled_flag; + #define __pyx_assertions_enabled() (__pyx_assertions_enabled_flag) + + #undef __Pyx_init_assertions_enabled + static void __Pyx_init_assertions_enabled(void) { + __pyx_assertions_enabled_flag = ! _PyInterpreterState_GetConfig(__Pyx_PyThreadState_Current->interp)->optimization_level; + } +#else + #define __pyx_assertions_enabled() (!Py_OptimizeFlag) +#endif + + +/////////////// ErrOccurredWithGIL.proto /////////////// +static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */ + +/////////////// ErrOccurredWithGIL /////////////// +static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) { + int err; + #ifdef WITH_THREAD + PyGILState_STATE _save = PyGILState_Ensure(); + #endif + err = !!PyErr_Occurred(); + #ifdef WITH_THREAD + PyGILState_Release(_save); + #endif + return err; +} + + /////////////// PyThreadStateGet.proto /////////////// //@substitute: naming @@ -127,9 +170,9 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject // has changed quite a lot between the two versions. #if PY_MAJOR_VERSION < 3 -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, - CYTHON_UNUSED PyObject *cause) { +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { __Pyx_PyThreadState_declare + CYTHON_UNUSED_VAR(cause); /* 'cause' is only used in Py3 */ Py_XINCREF(type); if (!value || value == Py_None) @@ -310,19 +353,19 @@ bad: /////////////// GetTopmostException.proto /////////////// -#if CYTHON_USE_EXC_INFO_STACK +#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); #endif /////////////// GetTopmostException /////////////// -#if CYTHON_USE_EXC_INFO_STACK +#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE // Copied from errors.c in CPython. static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate) { _PyErr_StackItem *exc_info = tstate->exc_info; - while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) && exc_info->previous_item != NULL) { exc_info = exc_info->previous_item; @@ -388,12 +431,21 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) #if CYTHON_USE_EXC_INFO_STACK { _PyErr_StackItem *exc_info = tstate->exc_info; + #if PY_VERSION_HEX >= 0x030B00a4 + tmp_value = exc_info->exc_value; + exc_info->exc_value = local_value; + tmp_type = NULL; + tmp_tb = NULL; + Py_XDECREF(local_type); + Py_XDECREF(local_tb); + #else tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = local_type; exc_info->exc_value = local_value; exc_info->exc_traceback = local_tb; + #endif } #else tmp_type = tstate->exc_type; @@ -433,35 +485,44 @@ static CYTHON_INLINE void __Pyx_ReraiseException(void) { PyObject *type = NULL, *value = NULL, *tb = NULL; #if CYTHON_FAST_THREAD_STATE PyThreadState *tstate = PyThreadState_GET(); - #if CYTHON_USE_EXC_INFO_STACK + #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); - type = exc_info->exc_type; value = exc_info->exc_value; - tb = exc_info->exc_traceback; + #if PY_VERSION_HEX >= 0x030B00a4 + if (unlikely(value == Py_None)) { + value = NULL; + } else if (value) { + Py_INCREF(value); + type = (PyObject*) Py_TYPE(value); + Py_INCREF(type); + tb = PyException_GetTraceback(value); + } #else + type = exc_info->exc_type; + tb = exc_info->exc_traceback; + Py_XINCREF(type); + Py_XINCREF(value); + Py_XINCREF(tb); + #endif + #else type = tstate->exc_type; value = tstate->exc_value; tb = tstate->exc_traceback; - #endif + Py_XINCREF(type); + Py_XINCREF(value); + Py_XINCREF(tb); + #endif #else PyErr_GetExcInfo(&type, &value, &tb); #endif - if (!type || type == Py_None) { -#if !CYTHON_FAST_THREAD_STATE + if (unlikely(!type || type == Py_None)) { Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(tb); -#endif // message copied from Py3 PyErr_SetString(PyExc_RuntimeError, "No active exception to reraise"); } else { -#if CYTHON_FAST_THREAD_STATE - Py_INCREF(type); - Py_XINCREF(value); - Py_XINCREF(tb); - -#endif PyErr_Restore(type, value, tb); } } @@ -487,24 +548,49 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { - #if CYTHON_USE_EXC_INFO_STACK + #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + PyObject *exc_value = exc_info->exc_value; + if (exc_value == NULL || exc_value == Py_None) { + *value = NULL; + *type = NULL; + *tb = NULL; + } else { + *value = exc_value; + Py_INCREF(*value); + *type = (PyObject*) Py_TYPE(exc_value); + Py_INCREF(*type); + *tb = PyException_GetTraceback(exc_value); + } + #elif CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); *type = exc_info->exc_type; *value = exc_info->exc_value; *tb = exc_info->exc_traceback; - #else + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); + #else *type = tstate->exc_type; *value = tstate->exc_value; *tb = tstate->exc_traceback; - #endif Py_XINCREF(*type); Py_XINCREF(*value); Py_XINCREF(*tb); + #endif } static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 + _PyErr_StackItem *exc_info = tstate->exc_info; + PyObject *tmp_value = exc_info->exc_value; + exc_info->exc_value = value; + Py_XDECREF(tmp_value); + // TODO: avoid passing these at all + Py_XDECREF(type); + Py_XDECREF(tb); + #else PyObject *tmp_type, *tmp_value, *tmp_tb; - #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; @@ -524,6 +610,7 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); + #endif } #endif @@ -543,8 +630,22 @@ static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; - - #if CYTHON_USE_EXC_INFO_STACK + #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_value = exc_info->exc_value; + exc_info->exc_value = *value; + if (tmp_value == NULL || tmp_value == Py_None) { + Py_XDECREF(tmp_value); + tmp_value = NULL; + tmp_type = NULL; + tmp_tb = NULL; + } else { + // TODO: avoid swapping these at all + tmp_type = (PyObject*) Py_TYPE(tmp_value); + Py_INCREF(tmp_type); + tmp_tb = PyException_GetTraceback(tmp_value); + } + #elif CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; @@ -553,7 +654,7 @@ static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject * exc_info->exc_type = *type; exc_info->exc_value = *value; exc_info->exc_traceback = *tb; - #else + #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; @@ -561,7 +662,7 @@ static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject * tstate->exc_type = *type; tstate->exc_value = *value; tstate->exc_traceback = *tb; - #endif + #endif *type = tmp_type; *value = tmp_value; @@ -590,9 +691,9 @@ static void __Pyx_WriteUnraisable(const char *name, int clineno, //@requires: PyErrFetchRestore //@requires: PyThreadStateGet -static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, - CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, - int full_traceback, CYTHON_UNUSED int nogil) { +static void __Pyx_WriteUnraisable(const char *name, int clineno, + int lineno, const char *filename, + int full_traceback, int nogil) { PyObject *old_exc, *old_val, *old_tb; PyObject *ctx; __Pyx_PyThreadState_declare @@ -600,9 +701,14 @@ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, PyGILState_STATE state; if (nogil) state = PyGILState_Ensure(); - /* initalize to suppress warning */ + /* arbitrary, to suppress warning */ else state = (PyGILState_STATE)0; #endif + CYTHON_UNUSED_VAR(clineno); + CYTHON_UNUSED_VAR(lineno); + CYTHON_UNUSED_VAR(filename); + CYTHON_MAYBE_UNUSED_VAR(nogil); + __Pyx_PyThreadState_assign __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); if (full_traceback) { @@ -639,19 +745,21 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line);/*proto*/ #endif /////////////// CLineInTraceback /////////////// -//@requires: ObjectHandling.c::PyObjectGetAttrStr +//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError //@requires: ObjectHandling.c::PyDictVersioning //@requires: PyErrFetchRestore //@substitute: naming #ifndef CYTHON_CLINE_IN_TRACEBACK -static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_line) { +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { PyObject *use_cline; PyObject *ptype, *pvalue, *ptraceback; #if CYTHON_COMPILING_IN_CPYTHON PyObject **cython_runtime_dict; #endif + CYTHON_MAYBE_UNUSED_VAR(tstate); + if (unlikely(!${cython_runtime_cname})) { // Very early error where the runtime module is not set up yet. return c_line; @@ -668,7 +776,7 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li } else #endif { - PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(${cython_runtime_cname}, PYIDENT("cline_in_traceback")); + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStrNoError(${cython_runtime_cname}, PYIDENT("cline_in_traceback")); if (use_cline_obj) { use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; Py_DECREF(use_cline_obj); @@ -710,6 +818,17 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, #include "internal/pycore_frame.h" #endif +#if CYTHON_COMPILING_IN_LIMITED_API +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + if (c_line) { + // Avoid "unused" warning as long as we don't use this. + (void) $cfilenm_cname; + (void) __Pyx_CLineForTraceback(__Pyx_PyThreadState_Current, c_line); + } + _PyTraceback_Add(funcname, filename, py_line); +} +#else static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { @@ -742,6 +861,7 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( #if PY_MAJOR_VERSION < 3 py_code = __Pyx_PyCode_New( 0, /*int argcount,*/ + 0, /*int posonlyargcount,*/ 0, /*int kwonlyargcount,*/ 0, /*int nlocals,*/ 0, /*int stacksize,*/ @@ -812,3 +932,4 @@ bad: Py_XDECREF(py_code); Py_XDECREF(py_frame); } +#endif |