static PyObject * Fiber_func_throw(Fiber *self, PyObject *args) { Fiber *current; PyObject *typ, *val, *tb; val = tb = NULL; if (!PyArg_ParseTuple(args, "O|OO:throw", &typ, &val, &tb)) { return NULL; } /* First, check the traceback argument, replacing None, with NULL */ if (tb == Py_None) { tb = NULL; } else if (tb != NULL && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback object"); return NULL; } Py_INCREF(typ); Py_XINCREF(val); Py_XINCREF(tb); if (PyExceptionClass_Check(typ)) { PyErr_NormalizeException(&typ, &val, &tb); } else if (PyExceptionInstance_Check(typ)) { /* Raising an instance. The value should be a dummy. */ if (val && val != Py_None) { PyErr_SetString(PyExc_TypeError, "instance exceptions cannot have a separate value"); goto error; } else { /* Normalize to raise <class>, <instance> */ Py_XDECREF(val); val = typ; typ = PyExceptionInstance_Class(typ); Py_INCREF(typ); } } else { /* Not something you can raise. throw() fails. */ PyErr_Format(PyExc_TypeError, "exceptions must be classes, or instances, not %s", Py_TYPE(typ)->tp_name); goto error; } if (!CHECK_STATE) { goto error; } current = _global_state.current; if (self == current) { PyErr_SetString(PyExc_FiberError, "cannot throw from a Fiber to itself"); goto error; } if (self->stacklet_h == EMPTY_STACKLET_HANDLE) { PyErr_SetString(PyExc_FiberError, "Fiber has ended"); goto error; } if (self->thread_h != current->thread_h) { PyErr_SetString(PyExc_FiberError, "cannot switch to a Fiber on a different thread"); return NULL; } /* set error and do a switch with NULL as the value */ PyErr_Restore(typ, val, tb); return do_switch(self, NULL); error: /* Didn't use our arguments, so restore their original refcounts */ Py_DECREF(typ); Py_XDECREF(val); Py_XDECREF(tb); return NULL; }
static PyObject * gen_throw(PyGenObject *gen, PyObject *args) { PyObject *typ; PyObject *tb = NULL; PyObject *val = NULL; PyObject *yf = _PyGen_yf(gen); _Py_IDENTIFIER(throw); if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) return NULL; if (yf) { PyObject *ret; int err; if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) { gen->gi_running = 1; err = gen_close_iter(yf); gen->gi_running = 0; Py_DECREF(yf); if (err < 0) return gen_send_ex(gen, Py_None, 1, 0); goto throw_here; } if (PyGen_CheckExact(yf)) { gen->gi_running = 1; ret = gen_throw((PyGenObject *)yf, args); gen->gi_running = 0; } else { PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw); if (meth == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { Py_DECREF(yf); return NULL; } PyErr_Clear(); Py_DECREF(yf); goto throw_here; } gen->gi_running = 1; ret = PyObject_CallObject(meth, args); gen->gi_running = 0; Py_DECREF(meth); } Py_DECREF(yf); if (!ret) { PyObject *val; /* Pop subiterator from stack */ ret = *(--gen->gi_frame->f_stacktop); assert(ret == yf); Py_DECREF(ret); /* Termination repetition of YIELD_FROM */ gen->gi_frame->f_lasti += 2; if (_PyGen_FetchStopIterationValue(&val) == 0) { ret = gen_send_ex(gen, val, 0, 0); Py_DECREF(val); } else { ret = gen_send_ex(gen, Py_None, 1, 0); } } return ret; } throw_here: /* First, check the traceback argument, replacing None with NULL. */ if (tb == Py_None) { tb = NULL; } else if (tb != NULL && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback object"); return NULL; } Py_INCREF(typ); Py_XINCREF(val); Py_XINCREF(tb); if (PyExceptionClass_Check(typ)) PyErr_NormalizeException(&typ, &val, &tb); else if (PyExceptionInstance_Check(typ)) { /* Raising an instance. The value should be a dummy. */ if (val && val != Py_None) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto failed_throw; } else { /* Normalize to raise <class>, <instance> */ Py_XDECREF(val); val = typ; typ = PyExceptionInstance_Class(typ); Py_INCREF(typ); if (tb == NULL) /* Returns NULL if there's no traceback */ tb = PyException_GetTraceback(val); } } else { /* Not something you can raise. throw() fails. */ PyErr_Format(PyExc_TypeError, "exceptions must be classes or instances " "deriving from BaseException, not %s", Py_TYPE(typ)->tp_name); goto failed_throw; } PyErr_Restore(typ, val, tb); return gen_send_ex(gen, Py_None, 1, 0); failed_throw: /* Didn't use our arguments, so restore their original refcounts */ Py_DECREF(typ); Py_XDECREF(val); Py_XDECREF(tb); return NULL; }
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { PyObject* owned_instance = NULL; if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto bad; } if (value == Py_None) value = 0; if (PyExceptionInstance_Check(type)) { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto bad; } value = type; type = (PyObject*) Py_TYPE(value); } else if (PyExceptionClass_Check(type)) { // make sure value is an exception instance of type PyObject *instance_class = NULL; if (value && PyExceptionInstance_Check(value)) { instance_class = (PyObject*) Py_TYPE(value); if (instance_class != type) { int is_subclass = PyObject_IsSubclass(instance_class, type); if (!is_subclass) { instance_class = NULL; } else if (unlikely(is_subclass == -1)) { // error on subclass test goto bad; } else { // believe the instance type = instance_class; } } } if (!instance_class) { // instantiate the type now (we don't know when and how it will be caught) // assuming that 'value' is an argument to the type's constructor // not using PyErr_NormalizeException() to avoid ref-counting problems PyObject *args; if (!value) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (!args) goto bad; owned_instance = PyObject_Call(type, args, NULL); Py_DECREF(args); if (!owned_instance) goto bad; value = owned_instance; if (!PyExceptionInstance_Check(value)) { PyErr_Format(PyExc_TypeError, "calling %R should have returned an instance of " "BaseException, not %R", type, Py_TYPE(value)); goto bad; } } } else { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto bad; } if (cause) { PyObject *fixed_cause; if (cause == Py_None) { // raise ... from None fixed_cause = NULL; } else if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto bad; } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; Py_INCREF(fixed_cause); } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " "BaseException"); goto bad; } PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); if (tb) { #if CYTHON_COMPILING_IN_PYPY PyObject *tmp_type, *tmp_value, *tmp_tb; PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); Py_INCREF(tb); PyErr_Restore(tmp_type, tmp_value, tb); Py_XDECREF(tmp_tb); #else PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject* tmp_tb = tstate->curexc_traceback; if (tb != tmp_tb) { Py_INCREF(tb); tstate->curexc_traceback = tb; Py_XDECREF(tmp_tb); } #endif } bad: Py_XDECREF(owned_instance); return; }
static PyObject *Nuitka_Generator_throw( struct Nuitka_GeneratorObject *generator, PyObject *args ) { assert( generator->m_exception_type == NULL ); assert( generator->m_exception_value == NULL ); assert( generator->m_exception_tb == NULL ); int res = PyArg_UnpackTuple( args, "throw", 1, 3, &generator->m_exception_type, &generator->m_exception_value, (PyObject **)&generator->m_exception_tb ); if (unlikely( res == 0 )) { generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; return NULL; } if ( (PyObject *)generator->m_exception_tb == Py_None ) { generator->m_exception_tb = NULL; } else if ( generator->m_exception_tb != NULL && !PyTraceBack_Check( generator->m_exception_tb ) ) { generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; PyErr_Format( PyExc_TypeError, "throw() third argument must be a traceback object" ); return NULL; } if ( PyExceptionClass_Check( generator->m_exception_type )) { Py_INCREF( generator->m_exception_type ); Py_XINCREF( generator->m_exception_value ); Py_XINCREF( generator->m_exception_tb ); NORMALIZE_EXCEPTION( &generator->m_exception_type, &generator->m_exception_value, &generator->m_exception_tb ); } else if ( PyExceptionInstance_Check( generator->m_exception_type ) ) { if ( generator->m_exception_value && generator->m_exception_value != Py_None ) { generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; PyErr_Format( PyExc_TypeError, "instance exception may not have a separate value" ); return NULL; } generator->m_exception_value = generator->m_exception_type; Py_INCREF( generator->m_exception_value ); generator->m_exception_type = PyExceptionInstance_Class( generator->m_exception_type ); Py_INCREF( generator->m_exception_type ); Py_XINCREF( generator->m_exception_tb ); } else { PyErr_Format( PyExc_TypeError, #if PYTHON_VERSION < 300 "exceptions must be classes, or instances, not %s", #else "exceptions must be classes or instances deriving from BaseException, not %s", #endif Py_TYPE( generator->m_exception_type )->tp_name ); generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; return NULL; } if ( ( generator->m_exception_tb != NULL ) && ( (PyObject *)generator->m_exception_tb != Py_None ) && ( !PyTraceBack_Check( generator->m_exception_tb ) ) ) { PyErr_Format( PyExc_TypeError, "throw() third argument must be a traceback object" ); return NULL; } if ( generator->m_status != status_Finished ) { PyObject *result = Nuitka_Generator_send( generator, Py_None ); return result; } else { RESTORE_ERROR_OCCURRED( generator->m_exception_type, generator->m_exception_value, generator->m_exception_tb ); generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; return NULL; } }
static PyObject * green_throw(PyGreenlet *self, PyObject *args) { PyObject *typ = PyExc_GreenletExit; PyObject *val = NULL; PyObject *tb = NULL; if (!PyArg_ParseTuple(args, "|OOO:throw", &typ, &val, &tb)) { return NULL; } /* First, check the traceback argument, replacing None, with NULL */ if (tb == Py_None) { tb = NULL; } else if (tb != NULL && !PyTraceBack_Check(tb)) { PyErr_SetString( PyExc_TypeError, "throw() third argument must be a traceback object"); return NULL; } Py_INCREF(typ); Py_XINCREF(val); Py_XINCREF(tb); if (PyExceptionClass_Check(typ)) { PyErr_NormalizeException(&typ, &val, &tb); } else if (PyExceptionInstance_Check(typ)) { /* Raising an instance. The value should be a dummy. */ if (val && val != Py_None) { PyErr_SetString( PyExc_TypeError, "instance exception may not have a separate value"); goto failed_throw; } else { /* Normalize to raise <class>, <instance> */ Py_XDECREF(val); val = typ; typ = PyExceptionInstance_Class(typ); Py_INCREF(typ); } } else { /* Not something you can raise. throw() fails. */ PyErr_Format( PyExc_TypeError, "exceptions must be classes, or instances, not %s", Py_TYPE(typ)->tp_name); goto failed_throw; } return throw_greenlet(self, typ, val, tb); failed_throw: /* Didn't use our arguments, so restore their original refcounts */ Py_DECREF(typ); Py_XDECREF(val); Py_XDECREF(tb); return NULL; }
NUITKA_MAY_BE_UNUSED static inline void RAISE_EXCEPTION_WITH_TRACEBACK( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb ) { CHECK_OBJECT( *exception_type ); CHECK_OBJECT( *exception_value ); if ( *exception_tb == (PyTracebackObject *)Py_None ) { Py_DECREF( *exception_tb ); *exception_tb = NULL; } // Non-empty tuple exceptions are the first element. while (unlikely( PyTuple_Check( *exception_type ) && PyTuple_Size( *exception_type ) > 0 )) { *exception_type = PyTuple_GET_ITEM( *exception_type, 0 ); } if ( PyExceptionClass_Check( *exception_type ) ) { NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb ); #if PYTHON_VERSION >= 270 if (unlikely( !PyExceptionInstance_Check( *exception_value ) )) { PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)*exception_type)->tp_name, Py_TYPE( *exception_value )->tp_name ); Py_DECREF( *exception_type ); Py_XDECREF( *exception_value ); Py_XDECREF( *exception_tb ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); } #endif return; } else if ( PyExceptionInstance_Check( *exception_type ) ) { if (unlikely( *exception_value != NULL && *exception_value != Py_None )) { PyErr_Format( PyExc_TypeError, "instance exception may not have a separate value" ); Py_DECREF( *exception_type ); Py_XDECREF( *exception_value ); Py_XDECREF( *exception_tb ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } // The type is rather a value, so we are overriding it here. *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class( *exception_type ); Py_INCREF( *exception_type ); return; } else { PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } }
static void print_exception(PyObject *f, PyObject *value) { int err = 0; PyObject *type, *tb; _Py_IDENTIFIER(print_file_and_line); if (!PyExceptionInstance_Check(value)) { err = PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); err += PyFile_WriteString(Py_TYPE(value)->tp_name, f); err += PyFile_WriteString(" found\n", f); if (err) PyErr_Clear(); return; } Py_INCREF(value); fflush(stdout); type = (PyObject *) Py_TYPE(value); tb = PyException_GetTraceback(value); if (tb && tb != Py_None) err = PyTraceBack_Print(tb, f); if (err == 0 && _PyObject_HasAttrId(value, &PyId_print_file_and_line)) { PyObject *message, *filename, *text; int lineno, offset; if (!parse_syntax_error(value, &message, &filename, &lineno, &offset, &text)) PyErr_Clear(); else { PyObject *line; Py_DECREF(value); value = message; line = PyUnicode_FromFormat(" File \"%U\", line %d\n", filename, lineno); Py_DECREF(filename); if (line != NULL) { PyFile_WriteObject(line, f, Py_PRINT_RAW); Py_DECREF(line); } if (text != NULL) { print_error_text(f, offset, text); Py_DECREF(text); } /* Can't be bothered to check all those PyFile_WriteString() calls */ if (PyErr_Occurred()) err = -1; } } if (err) { /* Don't do anything else */ } else { PyObject* moduleName; char* className; _Py_IDENTIFIER(__module__); assert(PyExceptionClass_Check(type)); className = PyExceptionClass_Name(type); if (className != NULL) { char *dot = strrchr(className, '.'); if (dot != NULL) className = dot+1; } moduleName = _PyObject_GetAttrId(type, &PyId___module__); if (moduleName == NULL || !PyUnicode_Check(moduleName)) { Py_XDECREF(moduleName); err = PyFile_WriteString("<unknown>", f); } else { if (_PyUnicode_CompareWithId(moduleName, &PyId_builtins) != 0) { err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW); err += PyFile_WriteString(".", f); } Py_DECREF(moduleName); } if (err == 0) { if (className == NULL) err = PyFile_WriteString("<unknown>", f); else err = PyFile_WriteString(className, f); } } if (err == 0 && (value != Py_None)) { PyObject *s = PyObject_Str(value); /* only print colon if the str() of the object is not the empty string */ if (s == NULL) err = -1; else if (!PyUnicode_Check(s) || PyUnicode_GetLength(s) != 0) err = PyFile_WriteString(": ", f); if (err == 0) err = PyFile_WriteObject(s, f, Py_PRINT_RAW); Py_XDECREF(s); } /* try to write a newline in any case */ err += PyFile_WriteString("\n", f); Py_XDECREF(tb); Py_DECREF(value); /* If an error happened here, don't show it. XXX This is wrong, but too many callers rely on this behavior. */ if (err != 0) PyErr_Clear(); }
/* Used in many places to normalize a raised exception, including in eval_code2(), do_raise(), and PyErr_Print() */ void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) { PyObject *type = *exc; PyObject *value = *val; PyObject *inclass = NULL; PyObject *initial_tb = NULL; if (type == NULL) { /* There was no exception, so nothing to do. */ return; } /* If PyErr_SetNone() was used, the value will have been actually set to NULL. */ if (!value) { value = Py_None; Py_INCREF(value); } if (PyExceptionInstance_Check(value)) inclass = PyExceptionInstance_Class(value); /* Normalize the exception so that if the type is a class, the value will be an instance. */ if (PyExceptionClass_Check(type)) { /* if the value was not an instance, or is not an instance whose class is (or is derived from) type, then use the value as an argument to instantiation of the type class. */ if (!inclass || !PyObject_IsSubclass(inclass, type)) { PyObject *args, *res; if (value == Py_None) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (args == NULL) goto finally; res = PyEval_CallObject(type, args); Py_DECREF(args); if (res == NULL) goto finally; Py_DECREF(value); value = res; } /* if the class of the instance doesn't exactly match the class of the type, believe the instance */ else if (inclass != type) { Py_DECREF(type); type = inclass; Py_INCREF(type); } } *exc = type; *val = value; return; finally: Py_DECREF(type); Py_DECREF(value); /* If the new exception doesn't set a traceback and the old exception had a traceback, use the old traceback for the new exception. It's better than nothing. */ initial_tb = *tb; PyErr_Fetch(exc, val, tb); if (initial_tb != NULL) { if (*tb == NULL) *tb = initial_tb; else Py_DECREF(initial_tb); } /* normalize recursively */ PyErr_NormalizeException(exc, val, tb); }
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { PyObject* owned_instance = NULL; if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto bad; } if (value == Py_None) value = 0; if (PyExceptionInstance_Check(type)) { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto bad; } value = type; type = (PyObject*) Py_TYPE(value); } else if (PyExceptionClass_Check(type)) { // make sure value is an exception instance of type PyObject *instance_class = NULL; if (value && PyExceptionInstance_Check(value)) { instance_class = (PyObject*) Py_TYPE(value); if (instance_class != type) { int is_subclass = PyObject_IsSubclass(instance_class, type); if (!is_subclass) { instance_class = NULL; } else if (unlikely(is_subclass == -1)) { // error on subclass test goto bad; } else { // believe the instance type = instance_class; } } } if (!instance_class) { // instantiate the type now (we don't know when and how it will be caught) // assuming that 'value' is an argument to the type's constructor // not using PyErr_NormalizeException() to avoid ref-counting problems PyObject *args; if (!value) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (!args) goto bad; owned_instance = PyObject_Call(type, args, NULL); Py_DECREF(args); if (!owned_instance) goto bad; value = owned_instance; if (!PyExceptionInstance_Check(value)) { PyErr_Format(PyExc_TypeError, "calling %R should have returned an instance of " "BaseException, not %R", type, Py_TYPE(value)); goto bad; } } } else { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto bad; } #if PY_VERSION_HEX >= 0x03030000 if (cause) { #else if (cause && cause != Py_None) { #endif PyObject *fixed_cause; if (cause == Py_None) { // raise ... from None fixed_cause = NULL; } else if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto bad; } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; Py_INCREF(fixed_cause); } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " "BaseException"); goto bad; } PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); if (tb) { #if CYTHON_COMPILING_IN_PYPY PyObject *tmp_type, *tmp_value, *tmp_tb; PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); Py_INCREF(tb); PyErr_Restore(tmp_type, tmp_value, tb); Py_XDECREF(tmp_tb); #else PyThreadState *tstate = PyThreadState_GET(); PyObject* tmp_tb = tstate->curexc_traceback; if (tb != tmp_tb) { Py_INCREF(tb); tstate->curexc_traceback = tb; Py_XDECREF(tmp_tb); } #endif } bad: Py_XDECREF(owned_instance); return; } #endif /////////////// GetException.proto /////////////// //@substitute: naming //@requires: PyThreadStateGet #if CYTHON_FAST_THREAD_STATE #define __Pyx_GetException(type, value, tb) __Pyx__GetException($local_tstate_cname, type, value, tb) static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); /*proto*/ #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ #endif /////////////// GetException /////////////// #if CYTHON_FAST_THREAD_STATE static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) { #endif PyObject *local_type, *local_value, *local_tb; #if CYTHON_FAST_THREAD_STATE PyObject *tmp_type, *tmp_value, *tmp_tb; local_type = tstate->curexc_type; local_value = tstate->curexc_value; local_tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; #else PyErr_Fetch(&local_type, &local_value, &local_tb); #endif PyErr_NormalizeException(&local_type, &local_value, &local_tb); #if CYTHON_FAST_THREAD_STATE if (unlikely(tstate->curexc_type)) #else if (unlikely(PyErr_Occurred())) #endif goto bad; #if PY_MAJOR_VERSION >= 3 if (local_tb) { if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) goto bad; } #endif // traceback may be NULL for freshly raised exceptions Py_XINCREF(local_tb); // exception state may be temporarily empty in parallel loops (race condition) Py_XINCREF(local_type); Py_XINCREF(local_value); *type = local_type; *value = local_value; *tb = local_tb; #if CYTHON_FAST_THREAD_STATE tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = local_type; tstate->exc_value = local_value; tstate->exc_traceback = local_tb; // Make sure tstate is in a consistent state when we XDECREF // these objects (DECREF may run arbitrary code). Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); #else PyErr_SetExcInfo(local_type, local_value, local_tb); #endif return 0; bad: *type = 0; *value = 0; *tb = 0; Py_XDECREF(local_type); Py_XDECREF(local_value); Py_XDECREF(local_tb); return -1; } /////////////// ReRaiseException.proto /////////////// static CYTHON_INLINE void __Pyx_ReraiseException(void); /*proto*/ /////////////// ReRaiseException.proto /////////////// static CYTHON_INLINE void __Pyx_ReraiseException(void) { PyObject *type = NULL, *value = NULL, *tb = NULL; #if CYTHON_FAST_THREAD_STATE PyThreadState *tstate = PyThreadState_GET(); type = tstate->exc_type; value = tstate->exc_value; tb = tstate->exc_traceback; #else PyErr_GetExcInfo(&type, &value, &tb); #endif if (!type || type == Py_None) { #if !CYTHON_FAST_THREAD_STATE 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); } }
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_VALUE( PyObject *exception_type, PyObject *value, PyObject *exception_tb ) { assertObject( exception_type ); PyTracebackObject *traceback = (PyTracebackObject *)exception_tb; // Non-empty tuple exceptions are the first element. while (unlikely( PyTuple_Check( exception_type ) && PyTuple_Size( exception_type ) > 0 )) { exception_type = PyTuple_GET_ITEM( exception_type, 0 ); } if ( PyExceptionClass_Check( exception_type ) ) { Py_INCREF( exception_type ); Py_XINCREF( value ); Py_XINCREF( traceback ); NORMALIZE_EXCEPTION( &exception_type, &value, &traceback ); #if PYTHON_VERSION >= 270 if (unlikely( !PyExceptionInstance_Check( value ) )) { PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)exception_type)->tp_name, Py_TYPE( value )->tp_name ); Py_DECREF( exception_type ); Py_XDECREF( value ); Py_XDECREF( traceback ); throw PythonException(); } #endif throw PythonException( exception_type, value, traceback ); } else if ( PyExceptionInstance_Check( exception_type ) ) { if (unlikely( value != NULL && value != Py_None )) { PyErr_Format( PyExc_TypeError, "instance exception may not have a separate value" ); throw PythonException(); } // The type is rather a value, so we are overriding it here. value = exception_type; exception_type = PyExceptionInstance_Class( exception_type ); throw PythonException( INCREASE_REFCOUNT( exception_type ), INCREASE_REFCOUNT( value ), INCREASE_REFCOUNT_X( traceback ) ); } else { PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); throw PythonException(); } }
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_TYPE( PyObject *exception_type, PyObject *exception_tb ) { PyTracebackObject *traceback = (PyTracebackObject *)exception_tb; assertObject( traceback ); assert( PyTraceBack_Check( traceback ) ); assertObject( exception_type ); if ( PyExceptionClass_Check( exception_type ) ) { PyObject *value = NULL; Py_INCREF( exception_type ); Py_XINCREF( traceback ); NORMALIZE_EXCEPTION( &exception_type, &value, &traceback ); #if PYTHON_VERSION >= 270 if (unlikely( !PyExceptionInstance_Check( value ) )) { Py_DECREF( exception_type ); Py_DECREF( value ); Py_XDECREF( traceback ); PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)exception_type)->tp_name, Py_TYPE( value )->tp_name ); throw PythonException(); } #endif #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( exception_type, value ); #endif throw PythonException( exception_type, value, traceback ); } else if ( PyExceptionInstance_Check( exception_type ) ) { PyObject *value = exception_type; exception_type = PyExceptionInstance_Class( exception_type ); #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( exception_type, value ); PyTracebackObject *prev = (PyTracebackObject *)PyException_GetTraceback( value ); if ( prev != NULL ) { assert( traceback->tb_next == NULL ); traceback->tb_next = prev; } PyException_SetTraceback( value, (PyObject *)traceback ); #endif throw PythonException( INCREASE_REFCOUNT( exception_type ), INCREASE_REFCOUNT( value ), INCREASE_REFCOUNT( traceback ) ); } else { PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); PythonException to_throw; to_throw.setTraceback( INCREASE_REFCOUNT( traceback ) ); throw to_throw; } }
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_CAUSE( PyObject *exception_type, PyObject *exception_cause, PyObject *exception_tb ) { PyTracebackObject *traceback = (PyTracebackObject *)exception_tb; assertObject( exception_type ); assertObject( exception_cause ); #if PYTHON_VERSION >= 330 // None is not a cause. if ( exception_cause == Py_None ) { exception_cause = NULL; } else #endif if ( PyExceptionClass_Check( exception_cause ) ) { exception_cause = PyObject_CallObject( exception_cause, NULL ); if (unlikely( exception_cause == NULL )) { throw PythonException(); } } else { Py_INCREF( exception_cause ); } #if PYTHON_VERSION >= 330 if (unlikely( exception_cause != NULL && !PyExceptionInstance_Check( exception_cause ) )) #else if (unlikely( !PyExceptionInstance_Check( exception_cause ) )) #endif { Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, "exception causes must derive from BaseException" ); throw PythonException(); } if ( PyExceptionClass_Check( exception_type ) ) { PyObject *value = NULL; Py_INCREF( exception_type ); Py_INCREF( traceback ); NORMALIZE_EXCEPTION( &exception_type, &value, &traceback ); if (unlikely( !PyExceptionInstance_Check( value ) )) { Py_DECREF( exception_type ); Py_XDECREF( value ); Py_DECREF( traceback ); Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)exception_type)->tp_name, Py_TYPE( value )->tp_name ); throw PythonException(); } PythonException to_throw( exception_type, value, traceback ); to_throw.setCause( exception_cause ); throw to_throw; } else if ( PyExceptionInstance_Check( exception_type ) ) { Py_XDECREF( exception_cause ); throw PythonException( INCREASE_REFCOUNT( PyExceptionInstance_Class( exception_type ) ), INCREASE_REFCOUNT( exception_type ), INCREASE_REFCOUNT( traceback ) ); } else { Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); PythonException to_throw; to_throw.setTraceback( INCREASE_REFCOUNT( traceback ) ); throw to_throw; } }
/* Used in many places to normalize a raised exception, including in eval_code2(), do_raise(), and PyErr_Print() XXX: should PyErr_NormalizeException() also call PyException_SetTraceback() with the resulting value and tb? */ void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) { PyObject *type = *exc; PyObject *value = *val; PyObject *inclass = NULL; PyObject *initial_tb = NULL; PyThreadState *tstate = NULL; if (type == NULL) { /* There was no exception, so nothing to do. */ return; } /* If PyErr_SetNone() was used, the value will have been actually set to NULL. */ if (!value) { value = Py_None; Py_INCREF(value); } if (PyExceptionInstance_Check(value)) inclass = PyExceptionInstance_Class(value); /* Normalize the exception so that if the type is a class, the value will be an instance. */ if (PyExceptionClass_Check(type)) { int is_subclass; if (inclass) { is_subclass = PyObject_IsSubclass(inclass, type); if (is_subclass < 0) goto finally; } else is_subclass = 0; /* if the value was not an instance, or is not an instance whose class is (or is derived from) type, then use the value as an argument to instantiation of the type class. */ if (!inclass || !is_subclass) { PyObject *fixed_value; fixed_value = _PyErr_CreateException(type, value); if (fixed_value == NULL) { goto finally; } Py_DECREF(value); value = fixed_value; } /* if the class of the instance doesn't exactly match the class of the type, believe the instance */ else if (inclass != type) { Py_DECREF(type); type = inclass; Py_INCREF(type); } } *exc = type; *val = value; return; finally: Py_DECREF(type); Py_DECREF(value); /* If the new exception doesn't set a traceback and the old exception had a traceback, use the old traceback for the new exception. It's better than nothing. */ initial_tb = *tb; PyErr_Fetch(exc, val, tb); if (initial_tb != NULL) { if (*tb == NULL) *tb = initial_tb; else Py_DECREF(initial_tb); } /* normalize recursively */ tstate = PyThreadState_GET(); if (++tstate->recursion_depth > Py_GetRecursionLimit()) { --tstate->recursion_depth; /* throw away the old exception and use the recursion error instead */ Py_INCREF(PyExc_RecursionError); Py_SETREF(*exc, PyExc_RecursionError); Py_INCREF(PyExc_RecursionErrorInst); Py_SETREF(*val, PyExc_RecursionErrorInst); /* just keeping the old traceback */ return; } PyErr_NormalizeException(exc, val, tb); --tstate->recursion_depth; }
NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_TYPE( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb ) { *exception_value = NULL; *exception_tb = NULL; #if PYTHON_VERSION < 300 // Next, repeatedly, replace a tuple exception with its first item while( PyTuple_Check( *exception_type ) && PyTuple_Size( *exception_type ) > 0 ) { PyObject *tmp = *exception_type; *exception_type = PyTuple_GET_ITEM( *exception_type, 0 ); Py_INCREF( *exception_type ); Py_DECREF( tmp ); } #endif if ( PyExceptionClass_Check( *exception_type ) ) { NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb ); #if PYTHON_VERSION >= 270 if (unlikely( !PyExceptionInstance_Check( *exception_value ) )) { PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)*exception_type)->tp_name, Py_TYPE( *exception_value )->tp_name ); Py_DECREF( *exception_type ); Py_DECREF( *exception_value ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } #endif #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( *exception_value ); #endif return; } else if ( PyExceptionInstance_Check( *exception_type ) ) { *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class( *exception_type ); Py_INCREF( *exception_type ); #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( *exception_value ); // TODO: Ever true? if ( *exception_tb ) { PyTracebackObject *prev = (PyTracebackObject *)PyException_GetTraceback( *exception_value ); if ( prev != NULL ) { assert( (*exception_tb)->tb_next == NULL ); (*exception_tb)->tb_next = prev; } PyException_SetTraceback( *exception_value, (PyObject *)(*exception_tb ? *exception_tb : (PyTracebackObject *)Py_None ) ); } *exception_tb = (PyTracebackObject *)PyException_GetTraceback( *exception_value ); #endif return; } else { Py_DECREF( *exception_type ); PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( *exception_type )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } }
/* Used in many places to normalize a raised exception, including in eval_code2(), do_raise(), and PyErr_Print() XXX: should PyErr_NormalizeException() also call PyException_SetTraceback() with the resulting value and tb? */ void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) { int recursion_depth = 0; PyObject *type, *value, *initial_tb; restart: type = *exc; if (type == NULL) { /* There was no exception, so nothing to do. */ return; } value = *val; /* If PyErr_SetNone() was used, the value will have been actually set to NULL. */ if (!value) { value = Py_None; Py_INCREF(value); } /* Normalize the exception so that if the type is a class, the value will be an instance. */ if (PyExceptionClass_Check(type)) { PyObject *inclass = NULL; int is_subclass = 0; if (PyExceptionInstance_Check(value)) { inclass = PyExceptionInstance_Class(value); is_subclass = PyObject_IsSubclass(inclass, type); if (is_subclass < 0) { goto error; } } /* If the value was not an instance, or is not an instance whose class is (or is derived from) type, then use the value as an argument to instantiation of the type class. */ if (!is_subclass) { PyObject *fixed_value = _PyErr_CreateException(type, value); if (fixed_value == NULL) { goto error; } Py_DECREF(value); value = fixed_value; } /* If the class of the instance doesn't exactly match the class of the type, believe the instance. */ else if (inclass != type) { Py_INCREF(inclass); Py_DECREF(type); type = inclass; } } *exc = type; *val = value; return; error: Py_DECREF(type); Py_DECREF(value); recursion_depth++; if (recursion_depth == Py_NORMALIZE_RECURSION_LIMIT) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth " "exceeded while normalizing an exception"); } /* If the new exception doesn't set a traceback and the old exception had a traceback, use the old traceback for the new exception. It's better than nothing. */ initial_tb = *tb; PyErr_Fetch(exc, val, tb); assert(*exc != NULL); if (initial_tb != NULL) { if (*tb == NULL) *tb = initial_tb; else Py_DECREF(initial_tb); } /* Abort when Py_NORMALIZE_RECURSION_LIMIT has been exceeded, and the corresponding RecursionError could not be normalized, and the MemoryError raised when normalize this RecursionError could not be normalized. */ if (recursion_depth >= Py_NORMALIZE_RECURSION_LIMIT + 2) { if (PyErr_GivenExceptionMatches(*exc, PyExc_MemoryError)) { Py_FatalError("Cannot recover from MemoryErrors " "while normalizing exceptions."); } else { Py_FatalError("Cannot recover from the recursive normalization " "of an exception."); } } goto restart; }
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto bad; } if (value == Py_None) value = 0; if (PyExceptionInstance_Check(type)) { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto bad; } value = type; type = (PyObject*) Py_TYPE(value); } else if (!PyExceptionClass_Check(type)) { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto bad; } if (cause) { PyObject *fixed_cause; if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto bad; } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; Py_INCREF(fixed_cause); } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " "BaseException"); goto bad; } if (!value) { value = PyObject_CallObject(type, NULL); } PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); if (tb) { PyThreadState *tstate = PyThreadState_GET(); PyObject* tmp_tb = tstate->curexc_traceback; if (tb != tmp_tb) { Py_INCREF(tb); tstate->curexc_traceback = tb; Py_XDECREF(tmp_tb); } } bad: return; }
void PyErr_SetObject(PyObject *exception, PyObject *value) { PyThreadState *tstate = PyThreadState_GET(); PyObject *exc_value; PyObject *tb = NULL; if (exception != NULL && !PyExceptionClass_Check(exception)) { PyErr_Format(PyExc_SystemError, "exception %R not a BaseException subclass", exception); return; } Py_XINCREF(value); exc_value = _PyErr_GetTopmostException(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 *fixed_value; /* Issue #23571: functions must not be called with an exception set */ PyErr_Clear(); fixed_value = _PyErr_CreateException(exception, value); Py_XDECREF(value); if (fixed_value == NULL) { Py_DECREF(exc_value); return; } value = fixed_value; } /* Avoid reference cycles through the context chain. This is O(chain length) but context chains are usually very short. Sensitive readers may try to inline the call to PyException_GetContext. */ if (exc_value != value) { PyObject *o = exc_value, *context; while ((context = PyException_GetContext(o))) { Py_DECREF(context); if (context == value) { PyException_SetContext(o, NULL); break; } o = context; } PyException_SetContext(value, exc_value); } else { Py_DECREF(exc_value); } } if (value != NULL && PyExceptionInstance_Check(value)) tb = PyException_GetTraceback(value); Py_XINCREF(exception); PyErr_Restore(exception, value, tb); }
NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_CAUSE( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb, PyObject *exception_cause ) { CHECK_OBJECT( *exception_type ); CHECK_OBJECT( exception_cause ); *exception_value = NULL; *exception_tb = NULL; #if PYTHON_VERSION >= 330 // None is not a cause. if ( exception_cause == Py_None ) { Py_DECREF( exception_cause ); exception_cause = NULL; } else #endif if ( PyExceptionClass_Check( exception_cause ) ) { PyObject *old_exception_cause = exception_cause; exception_cause = PyObject_CallObject( exception_cause, NULL ); Py_DECREF( old_exception_cause ); if (unlikely( exception_cause == NULL )) { Py_DECREF( *exception_type ); Py_XDECREF( *exception_tb ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } } #if PYTHON_VERSION >= 330 if (unlikely( exception_cause != NULL && !PyExceptionInstance_Check( exception_cause ) )) #else if (unlikely( !PyExceptionInstance_Check( exception_cause ) )) #endif { Py_DECREF( *exception_type ); Py_XDECREF( *exception_tb ); Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, "exception causes must derive from BaseException" ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } if ( PyExceptionClass_Check( *exception_type ) ) { NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb ); if (unlikely( !PyExceptionInstance_Check( *exception_value ) )) { Py_DECREF( *exception_type ); Py_XDECREF( *exception_value ); Py_DECREF( *exception_tb ); Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)exception_type)->tp_name, Py_TYPE( *exception_value )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } PyException_SetCause( *exception_value, exception_cause ); #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( *exception_value ); #endif return; } else if ( PyExceptionInstance_Check( *exception_type ) ) { *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class( *exception_type ); Py_INCREF( *exception_type ); PyException_SetCause( *exception_value, exception_cause ); #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( *exception_value ); #endif return; } else { Py_DECREF( *exception_type ); Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } }