static void _Py_PrintFatalError(int fd) { PyObject *ferr, *res; PyObject *exception, *v, *tb; int has_tb; PyThreadState *tstate; PyErr_Fetch(&exception, &v, &tb); if (exception == NULL) { /* No current exception */ goto display_stack; } ferr = _PySys_GetObjectId(&PyId_stderr); if (ferr == NULL || ferr == Py_None) { /* sys.stderr is not set yet or set to None, no need to try to display the exception */ goto display_stack; } PyErr_NormalizeException(&exception, &v, &tb); if (tb == NULL) { tb = Py_None; Py_INCREF(tb); } PyException_SetTraceback(v, tb); if (exception == NULL) { /* PyErr_NormalizeException() failed */ goto display_stack; } has_tb = (tb != Py_None); PyErr_Display(exception, v, tb); Py_XDECREF(exception); Py_XDECREF(v); Py_XDECREF(tb); /* sys.stderr may be buffered: call sys.stderr.flush() */ res = _PyObject_CallMethodId(ferr, &PyId_flush, ""); if (res == NULL) PyErr_Clear(); else Py_DECREF(res); if (has_tb) return; display_stack: #ifdef WITH_THREAD /* PyGILState_GetThisThreadState() works even if the GIL was released */ tstate = PyGILState_GetThisThreadState(); #else tstate = PyThreadState_GET(); #endif if (tstate == NULL) { /* _Py_DumpTracebackThreads() requires the thread state to display * frames */ return; } fputc('\n', stderr); fflush(stderr); /* display the current Python stack */ _Py_DumpTracebackThreads(fd, tstate->interp, tstate); }
/** * pygi_gerror_exception_check: * @error: a standard GLib GError ** output parameter * * Checks to see if a GError exception has been raised, and if so * translates the python exception to a standard GLib GError. If the * raised exception is not a GError then PyErr_Print() is called. * * Returns: 0 if no exception has been raised, -1 if it is a * valid glib.GError, -2 otherwise. */ gboolean pygi_gerror_exception_check (GError **error) { PyObject *type, *value, *traceback; PyObject *py_message, *py_domain, *py_code; const char *bad_gerror_message; PyErr_Fetch(&type, &value, &traceback); if (type == NULL) return 0; PyErr_NormalizeException(&type, &value, &traceback); if (value == NULL) { PyErr_Restore(type, value, traceback); PyErr_Print(); return -2; } if (!value || !PyErr_GivenExceptionMatches(type, (PyObject *) PyGError)) { PyErr_Restore(type, value, traceback); PyErr_Print(); return -2; } Py_DECREF(type); Py_XDECREF(traceback); py_message = PyObject_GetAttrString(value, "message"); if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) { bad_gerror_message = "GLib.Error instances must have a 'message' string attribute"; Py_XDECREF(py_message); goto bad_gerror; } py_domain = PyObject_GetAttrString(value, "domain"); if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) { bad_gerror_message = "GLib.Error instances must have a 'domain' string attribute"; Py_DECREF(py_message); Py_XDECREF(py_domain); goto bad_gerror; } py_code = PyObject_GetAttrString(value, "code"); if (!py_code || !PYGLIB_PyLong_Check(py_code)) { bad_gerror_message = "GLib.Error instances must have a 'code' int attribute"; Py_DECREF(py_message); Py_DECREF(py_domain); Py_XDECREF(py_code); goto bad_gerror; } g_set_error(error, g_quark_from_string(PYGLIB_PyUnicode_AsString(py_domain)), PYGLIB_PyLong_AsLong(py_code), "%s", PYGLIB_PyUnicode_AsString(py_message)); Py_DECREF(py_message); Py_DECREF(py_code); Py_DECREF(py_domain); return -1; bad_gerror: Py_DECREF(value); g_set_error(error, g_quark_from_static_string("pygi"), 0, "%s", bad_gerror_message); PyErr_SetString(PyExc_ValueError, bad_gerror_message); PyErr_Print(); return -2; }
static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) { PyObject *et, *ev, *tb; PyObject *value = NULL; __Pyx_ErrFetch(&et, &ev, &tb); if (!et) { Py_XDECREF(tb); Py_XDECREF(ev); Py_INCREF(Py_None); *pvalue = Py_None; return 0; } if (unlikely(et != PyExc_StopIteration) && unlikely(!PyErr_GivenExceptionMatches(et, PyExc_StopIteration))) { __Pyx_ErrRestore(et, ev, tb); return -1; } // most common case: plain StopIteration without or with separate argument if (likely(et == PyExc_StopIteration)) { if (likely(!ev) || !PyObject_IsInstance(ev, PyExc_StopIteration)) { // PyErr_SetObject() and friends put the value directly into ev if (!ev) { Py_INCREF(Py_None); ev = Py_None; } Py_XDECREF(tb); Py_DECREF(et); *pvalue = ev; return 0; } } // otherwise: normalise and check what that gives us PyErr_NormalizeException(&et, &ev, &tb); if (unlikely(!PyObject_IsInstance(ev, PyExc_StopIteration))) { // looks like normalisation failed - raise the new exception __Pyx_ErrRestore(et, ev, tb); return -1; } Py_XDECREF(tb); Py_DECREF(et); #if PY_VERSION_HEX >= 0x030300A0 value = ((PyStopIterationObject *)ev)->value; Py_INCREF(value); Py_DECREF(ev); #else { PyObject* args = PyObject_GetAttr(ev, PYIDENT("args")); Py_DECREF(ev); if (likely(args)) { value = PyObject_GetItem(args, 0); Py_DECREF(args); } if (unlikely(!value)) { __Pyx_ErrRestore(NULL, NULL, NULL); Py_INCREF(Py_None); value = Py_None; } } #endif *pvalue = value; return 0; }
/* 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 (PyInstance_Check(value)) inclass = (PyObject*)((PyInstanceObject*)value)->in_class; /* Normalize the exception so that if the type is a class, the value will be an instance. */ if (PyClass_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 || !PyClass_IsSubclass(inclass, type)) { PyObject *args, *res; if (value == Py_None) args = Py_BuildValue("()"); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = Py_BuildValue("(O)", 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 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; }
void python_handle_exception(const char *fmt, ...) { PyObject *pResult; const char *msg; char *buf; size_t buflen, msglen; PyObject *exception, *v, *tb, *args; PyObject *line; int i; char *srcbuf; // We don't want to generate traceback when no errors occured if (!PyErr_Occurred()) return; if (fmt == NULL) srcbuf = NULL; else srcbuf = make_message(fmt); PyErr_Fetch(&exception, &v, &tb); PyErr_Clear(); if (exception == NULL) { LM_ERR("python_handle_exception(): Can't get traceback, PyErr_Fetch() has failed.\n"); return; } PyErr_NormalizeException(&exception, &v, &tb); if (exception == NULL) { LM_ERR("python_handle_exception(): Can't get traceback, PyErr_NormalizeException() has failed.\n"); return; } args = PyTuple_Pack(3, exception, v, tb ? tb : Py_None); Py_XDECREF(exception); Py_XDECREF(v); Py_XDECREF(tb); if (args == NULL) { LM_ERR("python_handle_exception(): Can't get traceback, PyTuple_Pack() has failed.\n"); return; } pResult = PyObject_CallObject(format_exc_obj, args); Py_DECREF(args); if (pResult == NULL) { LM_ERR("python_handle_exception(): Can't get traceback, traceback.format_exception() has failed.\n"); return; } buflen = 1; buf = (char *)pkg_realloc(NULL, buflen * sizeof(char *)); if (!buf) { LM_ERR("python_handle_exception(): Can't allocate memory (%lu bytes), pkg_realloc() has failed. Not enough memory.\n", buflen * sizeof(char *)); return; } memset(buf, 0, sizeof(char *)); for (i = 0; i < PySequence_Size(pResult); i++) { line = PySequence_GetItem(pResult, i); if (line == NULL) { LM_ERR("python_handle_exception(): Can't get traceback, PySequence_GetItem() has failed.\n"); Py_DECREF(pResult); if (buf) pkg_free(buf); return; } msg = PyString_AsString(line); if (msg == NULL) { LM_ERR("python_handle_exception(): Can't get traceback, PyString_AsString() has failed.\n"); Py_DECREF(line); Py_DECREF(pResult); if (buf) pkg_free(buf); return; } msglen = strlen(msg); buflen += ++msglen; buf = (char *)pkg_realloc(buf, buflen * sizeof(char *)); if (!buf) { LM_ERR("python_handle_exception(): Can't allocate memory (%li bytes), pkg_realloc() has failed. Not enough memory.\n", buflen * sizeof(char *)); Py_DECREF(line); Py_DECREF(pResult); return; } strncat(buf, msg, msglen >= buflen ? buflen-1 : msglen); Py_DECREF(line); } if (srcbuf == NULL) LM_ERR("Unhandled exception in the Python code:\n%s", buf); else LM_ERR("%s: Unhandled exception in the Python code:\n%s", srcbuf, buf); if (buf) pkg_free(buf); if (srcbuf) pkg_free(srcbuf); Py_DECREF(pResult); }
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; }
QString QPythonPriv::formatExc() { PyObject *type = NULL; PyObject *value = NULL; PyObject *traceback = NULL; PyObject *list = NULL; PyObject *n = NULL; PyObject *s = NULL; PyErr_Fetch(&type, &value, &traceback); PyErr_NormalizeException(&type, &value, &traceback); QString message; QVariant v; if (type == NULL && value == NULL && traceback == NULL) { // No exception thrown? goto cleanup; } if (value != NULL) { // We can at least format the exception as string message = convertPyObjectToQVariant(PyObject_Str(value)).toString(); } if (type == NULL || traceback == NULL) { // Cannot get a traceback for this exception goto cleanup; } list = PyObject_CallMethod(traceback_mod, "format_exception", "OOO", type, value, traceback); if (list == NULL) { // Could not format exception, fall back to original message PyErr_Print(); goto cleanup; } n = PyUnicode_FromString("\n"); if (n == NULL) { PyErr_Print(); goto cleanup; } s = PyUnicode_Join(n, list); if (s == NULL) { PyErr_Print(); goto cleanup; } v = convertPyObjectToQVariant(s); if (v.isValid()) { message = v.toString(); } cleanup: Py_XDECREF(s); Py_XDECREF(n); Py_XDECREF(list); Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(traceback); qDebug() << QString("PyOtherSide error: %1").arg(message); return message; }
PyObject* NS(ErrorSet)( PyObject *self ) { SETUP_context PyObject *typeO = NULL, *valueO=NULL, *tbO = NULL, *retO = Py_None; PyThreadState *tstate = PyThreadState_Get(); if (tstate->curexc_type == NULL || tstate->curexc_type == Py_None) { typeO = tstate->exc_type; valueO = tstate->exc_value; tbO = tstate->exc_traceback; } else { typeO = tstate->curexc_type; valueO = tstate->curexc_value; tbO = tstate->curexc_traceback; } Py_XINCREF(typeO); Py_XINCREF(valueO); Py_XINCREF(tbO); PyErr_Clear(); { PyObject *valO = NULL ; if (typeO == Py_None || typeO == NULL) { MqErrorC (context, __func__, -1, "No active exception to reraise"); } else if (PyErr_GivenExceptionMatches(typeO,NS(MqSException))) { MqErrorSet (context, (MQ_INT) PyLong_AsLong(PyObject_GetAttrString(typeO,"num")), (enum MqErrorE) PyLong_AsLong(PyObject_GetAttrString(typeO,"code")), (MQ_CST const) PyBytes_AsString(PyUnicode_AsUTF8String(PyObject_GetAttrString(typeO,"text"))), NULL ); } else if (valueO) { PyObject *tmod = NULL, *strO = NULL, *lstO = NULL; PyErrorCheckNT(end1, tmod = PyImport_ImportModule("traceback")); if (tbO) { PyErr_NormalizeException(&typeO, &valueO, &tbO); PyErrorCheckNT(end1, lstO = PyObject_CallMethod(tmod, "format_exception", "OOO", typeO, valueO, tbO)); } else { PyErrorCheckNT(end1, lstO = PyObject_CallMethod(tmod, "format_exception_only", "OO", typeO, valueO)); } PyErrorCheckNT(end1, strO = PyC2O("")); PyErrorCheckNT(end1, valO = PyObject_CallMethod(strO, "join", "O", lstO)); end1: Py_XDECREF(tmod); Py_XDECREF(lstO); Py_XDECREF(strO); if (valO != NULL) { PyObject *strO=NULL, *utf8=NULL; PyErrorCheckNT(end2, strO = PyObject_Str(valO)); PyErrorCheckNT(end2, utf8 = PyUnicode_AsUTF8String(strO)); MqErrorC(context, __func__, -1, PyBytes_AsString(utf8)); end2: Py_XDECREF(utf8); Py_XDECREF(strO); } if (MqErrorGetCodeI(context) != MQ_ERROR) MqErrorV(context, __func__, -1, "%s: python error", PyExceptionClass_Name(typeO)); } } Py_XDECREF(typeO); Py_XDECREF(valueO); Py_XDECREF(tbO); Py_XINCREF(retO); return retO; }
static PyObject *cdefer_Deferred__runCallbacks(cdefer_Deferred *self) { PyObject *cb; PyObject *item; PyObject *callbacktuple; PyObject *callback; PyObject *args; PyObject *newArgs; PyObject *newArgs2; PyObject *kwargs; PyObject *_continue; PyObject *type, *value, *traceback; PyObject *tmp; PyObject *result; int size; int offset; const char *callback_name; if (self->running_callbacks) { Py_INCREF(Py_None); return Py_None; } if (!self->paused) { cb = self->callbacks; if (!PyList_Check(cb)) { PyErr_SetString(PyExc_TypeError, "callbacks must be a list"); return NULL; } for (;;) { size = PyList_GET_SIZE(cb); if (size == -1) { return NULL; } if (self->callback_index >= size) { break; } item = PyList_GET_ITEM(cb, self->callback_index); if (!item) { return NULL; } if (cdefer_Deferred__verify_callbacks_item(item)) { return NULL; } if (PyObject_IsInstance(self->result, failure_class)) { offset = 1; callback_name = "errback"; } else { offset = 0; callback_name = "callback"; } callbacktuple = PyTuple_GET_ITEM(item, offset); if (!callbacktuple) { return NULL; } if (cdefer_Deferred__verify_callback_entry(callback_name, callbacktuple)) { return NULL; } callback = PyTuple_GET_ITEM(callbacktuple, 0); if(!callback) { return NULL; } if (callback == Py_None) { ++self->callback_index; continue; } args = PyTuple_GET_ITEM(callbacktuple, 1); if (!args) { return NULL; } kwargs = PyTuple_GET_ITEM(callbacktuple, 2); if (!kwargs) { return NULL; } newArgs = Py_BuildValue("(O)", self->result); if (!newArgs) { return NULL; } if (args != Py_None) { newArgs2 = PySequence_InPlaceConcat(newArgs, args); Py_CLEAR(newArgs); if (!newArgs2) { return NULL; } } else { newArgs2 = newArgs; newArgs = NULL; } ++self->callback_index; if (kwargs == Py_None) { kwargs = NULL; } self->running_callbacks = 1; tmp = PyObject_Call(callback, newArgs2, kwargs); self->running_callbacks = 0; Py_DECREF(self->result); self->result = tmp; Py_CLEAR(newArgs2); if (!self->result) { PyErr_Fetch(&type, &value, &traceback); PyErr_NormalizeException(&type, &value, &traceback); if (!traceback) { traceback = Py_None; Py_INCREF(traceback); } self->result = PyObject_CallFunction(failure_class, "OOO", value, type, traceback); if (!self->result) { PyErr_Restore(type, value, traceback); return NULL; } Py_DECREF(type); Py_DECREF(value); Py_DECREF(traceback); continue; } if (PyObject_TypeCheck(self->result, &cdefer_DeferredType)) { PyObject *self_result; if (PyList_SetSlice(cb, 0, self->callback_index, NULL) == -1) { return NULL; } self->callback_index = 0; result = PyObject_CallMethod((PyObject *)self, "pause", NULL); if (!result) { return NULL; } Py_DECREF(result); _continue = PyObject_GetAttrString((PyObject *)self, "_continue"); if (!_continue) { return NULL; } self_result = self->result; Py_INCREF(self_result); result = cdefer_Deferred__addCallbacks( (cdefer_Deferred *)self->result, _continue, _continue, Py_None, Py_None, Py_None, Py_None); Py_DECREF(self_result); /* The reference was either copied/incref'd or not * (when errored) in addCallbacks, either way, we own * one too, and don't need it anymore. */ Py_DECREF(_continue); if (!result) { return NULL; } Py_DECREF(result); goto endLabel; } } if (PyList_SetSlice(cb, 0, PyList_GET_SIZE(cb), NULL) == -1) { return NULL; } self->callback_index = 0; } endLabel: if (PyObject_IsInstance(self->result, failure_class)) { result = PyObject_CallMethod((PyObject *)self->result, "cleanFailure", NULL); if (!result) { return NULL; } Py_DECREF(result); if (cdefer_Deferred__set_debuginfo_fail_result(self) == -1) { return NULL; } } else { if (cdefer_Deferred__clear_debuginfo(self) == -1) { return NULL; } } Py_INCREF(Py_None); return Py_None; }
void PyErr_PrintEx(int set_sys_last_vars) { PyObject *exception, *v, *tb, *hook; if (PyErr_ExceptionMatches(PyExc_SystemExit)) { handle_system_exit(); } PyErr_Fetch(&exception, &v, &tb); if (exception == NULL) return; PyErr_NormalizeException(&exception, &v, &tb); if (tb == NULL) { tb = Py_None; Py_INCREF(tb); } PyException_SetTraceback(v, tb); if (exception == NULL) return; /* Now we know v != NULL too */ if (set_sys_last_vars) { if (_PySys_SetObjectId(&PyId_last_type, exception) < 0) { PyErr_Clear(); } if (_PySys_SetObjectId(&PyId_last_value, v) < 0) { PyErr_Clear(); } if (_PySys_SetObjectId(&PyId_last_traceback, tb) < 0) { PyErr_Clear(); } } hook = _PySys_GetObjectId(&PyId_excepthook); if (hook) { PyObject* stack[3]; PyObject *result; stack[0] = exception; stack[1] = v; stack[2] = tb; result = _PyObject_FastCall(hook, stack, 3); if (result == NULL) { PyObject *exception2, *v2, *tb2; if (PyErr_ExceptionMatches(PyExc_SystemExit)) { handle_system_exit(); } PyErr_Fetch(&exception2, &v2, &tb2); PyErr_NormalizeException(&exception2, &v2, &tb2); /* It should not be possible for exception2 or v2 to be NULL. However PyErr_Display() can't tolerate NULLs, so just be safe. */ if (exception2 == NULL) { exception2 = Py_None; Py_INCREF(exception2); } if (v2 == NULL) { v2 = Py_None; Py_INCREF(v2); } fflush(stdout); PySys_WriteStderr("Error in sys.excepthook:\n"); PyErr_Display(exception2, v2, tb2); PySys_WriteStderr("\nOriginal exception was:\n"); PyErr_Display(exception, v, tb); Py_DECREF(exception2); Py_DECREF(v2); Py_XDECREF(tb2); } Py_XDECREF(result); } else { PySys_WriteStderr("sys.excepthook is missing\n"); PyErr_Display(exception, v, tb); } Py_XDECREF(exception); Py_XDECREF(v); Py_XDECREF(tb); }
static int _cffi_initialize_python(void) { /* This initializes Python, imports _cffi_backend, and then the present .dll/.so is set up as a CPython C extension module. */ int result; PyGILState_STATE state; PyObject *pycode=NULL, *global_dict=NULL, *x; #if PY_MAJOR_VERSION >= 3 /* see comments in _cffi_carefully_make_gil() about the Python2/Python3 difference */ #else /* Acquire the GIL. We have no threadstate here. If Python is already initialized, it is possible that there is already one existing for this thread, but it is not made current now. */ PyEval_AcquireLock(); _cffi_py_initialize(); /* The Py_InitializeEx() sometimes made a threadstate for us, but not always. Indeed Py_InitializeEx() could be called and do nothing. So do we have a threadstate, or not? We don't know, but we can replace it with NULL in all cases. */ (void)PyThreadState_Swap(NULL); /* Now we can release the GIL and re-acquire immediately using the logic of PyGILState(), which handles making or installing the correct threadstate. */ PyEval_ReleaseLock(); #endif state = PyGILState_Ensure(); /* Call the initxxx() function from the present module. It will create and initialize us as a CPython extension module, instead of letting the startup Python code do it---it might reimport the same .dll/.so and get maybe confused on some platforms. It might also have troubles locating the .dll/.so again for all I know. */ (void)_CFFI_PYTHON_STARTUP_FUNC(); if (PyErr_Occurred()) goto error; /* Now run the Python code provided to ffi.embedding_init_code(). */ pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE, "<init code for '" _CFFI_MODULE_NAME "'>", Py_file_input); if (pycode == NULL) goto error; global_dict = PyDict_New(); if (global_dict == NULL) goto error; if (PyDict_SetItemString(global_dict, "__builtins__", PyThreadState_GET()->interp->builtins) < 0) goto error; x = PyEval_EvalCode( #if PY_MAJOR_VERSION < 3 (PyCodeObject *) #endif pycode, global_dict, global_dict); if (x == NULL) goto error; Py_DECREF(x); /* Done! Now if we've been called from _cffi_start_and_call_python() in an ``extern "Python"``, we can only hope that the Python code did correctly set up the corresponding @ffi.def_extern() function. Otherwise, the general logic of ``extern "Python"`` functions (inside the _cffi_backend module) will find that the reference is still missing and print an error. */ result = 0; done: Py_XDECREF(pycode); Py_XDECREF(global_dict); PyGILState_Release(state); return result; error:; { /* Print as much information as potentially useful. Debugging load-time failures with embedding is not fun */ PyObject *exception, *v, *tb, *f, *modules, *mod; PyErr_Fetch(&exception, &v, &tb); if (exception != NULL) { PyErr_NormalizeException(&exception, &v, &tb); PyErr_Display(exception, v, tb); } Py_XDECREF(exception); Py_XDECREF(v); Py_XDECREF(tb); f = PySys_GetObject((char *)"stderr"); if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME "\ncompiled with cffi version: 1.5.1" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); if (mod == NULL) { PyFile_WriteString("not loaded", f); } else { v = PyObject_GetAttrString(mod, "__file__"); PyFile_WriteObject(v, f, 0); Py_XDECREF(v); } PyFile_WriteString("\nsys.path: ", f); PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0); PyFile_WriteString("\n\n", f); } } result = -1; goto done; }
std::string getPythonTraceback() { // get exception info PyObject *type, *value, *traceback; PyErr_Fetch(&type, &value, &traceback); PyErr_NormalizeException(&type, &value, &traceback); std::ostringstream mssg; if (traceback) { PyObject* tracebackModule; PyObject* tracebackDictionary; PyObject* tracebackFunction; tracebackModule = PyImport_ImportModule("traceback"); if (!tracebackModule) { throw python_error("unable to load traceback module while importing numpy inside PDAL"); } tracebackDictionary = PyModule_GetDict(tracebackModule); tracebackFunction = PyDict_GetItemString(tracebackDictionary, "format_exception"); if (!tracebackFunction) { throw python_error("unable to find traceback function while importing numpy inside PDAL"); } if (!PyCallable_Check(tracebackFunction)) { throw python_error("invalid traceback function while importing numpy inside PDAL"); } // create an argument for "format exception" PyObject* args = PyTuple_New(3); PyTuple_SetItem(args, 0, type); PyTuple_SetItem(args, 1, value); PyTuple_SetItem(args, 2, traceback); // get a list of string describing what went wrong PyObject* output = PyObject_CallObject(tracebackFunction, args); // print error message int i, n = PyList_Size(output); #if PY_MAJOR_VERSION >= 3 for (i=0; i<n; i++) { PyObject* u = PyUnicode_AsUTF8String(PyList_GetItem(output, i)); const char* p = PyBytes_AsString(u); mssg << p; } #else for (i=0; i<n; i++) mssg << PyString_AsString(PyList_GetItem(output, i)); #endif // clean up Py_XDECREF(args); Py_XDECREF(output); } else if (value != NULL) { PyObject *s = PyObject_Str(value); #if PY_MAJOR_VERSION >= 3 // const char* text = PyUnicode_AS_DATA(s); PyObject* u = PyUnicode_AsUTF8String(s); const char* text = PyBytes_AsString(u); #else const char* text = PyString_AS_STRING(s); #endif Py_DECREF(s); mssg << text; } else { mssg << "unknown error that we are unable to get a traceback for. Was it already printed/taken?"; } Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(traceback); return mssg.str(); }
/* * Emit a PG error or notice, together with any available info about * the current Python error, previously set by PLy_exception_set(). * This should be used to propagate Python errors into PG. If fmt is * NULL, the Python error becomes the primary error message, otherwise * it becomes the detail. If there is a Python traceback, it is put * in the context. */ void PLy_elog(int elevel, const char *fmt,...) { char *xmsg; char *tbmsg; int tb_depth; StringInfoData emsg; PyObject *exc, *val, *tb; const char *primary = NULL; int sqlerrcode = 0; char *detail = NULL; char *hint = NULL; char *query = NULL; int position = 0; PyErr_Fetch(&exc, &val, &tb); if (exc != NULL) { PyErr_NormalizeException(&exc, &val, &tb); if (PyErr_GivenExceptionMatches(val, PLy_exc_spi_error)) PLy_get_spi_error_data(val, &sqlerrcode, &detail, &hint, &query, &position); else if (PyErr_GivenExceptionMatches(val, PLy_exc_fatal)) elevel = FATAL; } /* this releases our refcount on tb! */ PLy_traceback(exc, val, tb, &xmsg, &tbmsg, &tb_depth); if (fmt) { initStringInfo(&emsg); for (;;) { va_list ap; int needed; va_start(ap, fmt); needed = appendStringInfoVA(&emsg, dgettext(TEXTDOMAIN, fmt), ap); va_end(ap); if (needed == 0) break; enlargeStringInfo(&emsg, needed); } primary = emsg.data; /* Since we have a format string, we cannot have a SPI detail. */ Assert(detail == NULL); /* If there's an exception message, it goes in the detail. */ if (xmsg) detail = xmsg; } else { if (xmsg) primary = xmsg; } PG_TRY(); { ereport(elevel, (errcode(sqlerrcode ? sqlerrcode : ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), errmsg_internal("%s", primary ? primary : "no exception data"), (detail) ? errdetail_internal("%s", detail) : 0, (tb_depth > 0 && tbmsg) ? errcontext("%s", tbmsg) : 0, (hint) ? errhint("%s", hint) : 0, (query) ? internalerrquery(query) : 0, (position) ? internalerrposition(position) : 0)); } PG_CATCH(); { if (fmt) pfree(emsg.data); if (xmsg) pfree(xmsg); if (tbmsg) pfree(tbmsg); Py_XDECREF(exc); Py_XDECREF(val); PG_RE_THROW(); } PG_END_TRY(); if (fmt) pfree(emsg.data); if (xmsg) pfree(xmsg); if (tbmsg) pfree(tbmsg); Py_XDECREF(exc); Py_XDECREF(val); }
int py_plugin_open(struct plugin *plugin, char *dir) { PyObject *handle, *info; PyObject *PyStr; PyObject *PyErrType, *PyErr, *PyTraceback; if (!(PyStr = PyString_FromString(dir))) { PyErr_Print(); return -1; } if (PyList_Insert(PyPath, 0, PyStr)) { Py_DECREF(PyStr); return -1; } if (!(handle = PyImport_ImportModule(plugin->name))) { /* ignore "module not found" errors in top level module */ PyErr_Fetch(&PyErrType, &PyErr, &PyTraceback); PyErr_NormalizeException(&PyErrType, &PyErr, &PyTraceback); if (PyErr_GivenExceptionMatches(PyErr, PyExc_ImportError) && !PyTraceback) { Py_XDECREF(PyErrType); Py_XDECREF(PyErr); } else { PyErr_Restore(PyErrType, PyErr, PyTraceback); PyErr_Print(); } if (PySequence_DelItem(PyPath, 0)) { PyErr_Print(); } Py_DECREF(PyStr); return -1; } if (PySequence_DelItem(PyPath, 0)) { PyErr_Print(); } Py_DECREF(PyStr); if (!(plugin->p = malloc(sizeof(struct py_plugin)))) { wminput_err("Error allocating py_plugin"); return -1; } plugin->type = PLUGIN_PYTHON; plugin->info = NULL; plugin->data = NULL; ((struct py_plugin *) plugin->p)->init = NULL; ((struct py_plugin *) plugin->p)->exec = NULL; if (!(plugin->info = malloc(sizeof *plugin->info))) { wminput_err("Error allocating plugin info"); goto ERR_HND; } if (!(plugin->data = malloc(sizeof *plugin->data))) { wminput_err("Error allocating plugin data"); goto ERR_HND; } if (!(((struct py_plugin *)plugin->p)->init = PyObject_GetAttrString(handle, "wmplugin_init"))) { PyErr_Print(); goto ERR_HND; } if (!PyCallable_Check(((struct py_plugin *)plugin->p)->init)) { wminput_err("Unable to load plugin init function: not callable"); goto ERR_HND; } if (!(((struct py_plugin *)plugin->p)->exec = PyObject_GetAttrString(handle, "wmplugin_exec"))) { PyErr_Print(); goto ERR_HND; } if (!PyCallable_Check(((struct py_plugin *)plugin->p)->exec)) { wminput_err("Unable to load plugin exec function: not callable"); goto ERR_HND; } if (!(info = PyObject_GetAttrString(handle, "wmplugin_info"))) { PyErr_Print(); goto ERR_HND; } if (!PyCallable_Check(info)) { wminput_err("Unable to load plugin info function: not callable"); Py_DECREF((PyObject *)info); goto ERR_HND; } if (py_plugin_info(plugin, info)) { wminput_err("Error on python_info"); Py_DECREF((PyObject *)info); goto ERR_HND; } Py_DECREF((PyObject *)info); ((struct py_plugin *) plugin->p)->handle = handle; return 0; ERR_HND: if (plugin->info) { free(plugin->info); } if (plugin->data) { free(plugin->data); } if (plugin->p) { if (((struct py_plugin *)plugin->p)->init) { Py_DECREF(((struct py_plugin *)plugin->p)->init); } if (((struct py_plugin *)plugin->p)->exec) { Py_DECREF(((struct py_plugin *)plugin->p)->exec); } free(plugin->p); } Py_DECREF(handle); return -1; }
void PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset) { PyObject *exc, *v, *tb, *tmp; _Py_IDENTIFIER(filename); _Py_IDENTIFIER(lineno); _Py_IDENTIFIER(msg); _Py_IDENTIFIER(offset); _Py_IDENTIFIER(print_file_and_line); _Py_IDENTIFIER(text); /* add attributes for the line number and filename for the error */ PyErr_Fetch(&exc, &v, &tb); PyErr_NormalizeException(&exc, &v, &tb); /* XXX check that it is, indeed, a syntax error. It might not * be, though. */ tmp = PyLong_FromLong(lineno); if (tmp == NULL) PyErr_Clear(); else { if (_PyObject_SetAttrId(v, &PyId_lineno, tmp)) PyErr_Clear(); Py_DECREF(tmp); } if (col_offset >= 0) { tmp = PyLong_FromLong(col_offset); if (tmp == NULL) PyErr_Clear(); else { if (_PyObject_SetAttrId(v, &PyId_offset, tmp)) PyErr_Clear(); Py_DECREF(tmp); } } if (filename != NULL) { if (_PyObject_SetAttrId(v, &PyId_filename, filename)) PyErr_Clear(); tmp = PyErr_ProgramTextObject(filename, lineno); if (tmp) { if (_PyObject_SetAttrId(v, &PyId_text, tmp)) PyErr_Clear(); Py_DECREF(tmp); } } if (_PyObject_SetAttrId(v, &PyId_offset, Py_None)) { PyErr_Clear(); } if (exc != PyExc_SyntaxError) { if (!_PyObject_HasAttrId(v, &PyId_msg)) { tmp = PyObject_Str(v); if (tmp) { if (_PyObject_SetAttrId(v, &PyId_msg, tmp)) PyErr_Clear(); Py_DECREF(tmp); } else { PyErr_Clear(); } } if (!_PyObject_HasAttrId(v, &PyId_print_file_and_line)) { if (_PyObject_SetAttrId(v, &PyId_print_file_and_line, Py_None)) PyErr_Clear(); } } PyErr_Restore(exc, v, tb); }
void reportPythonError( QString moduleName ) { // Print the Error if( PyErr_Occurred() ) { PyObject *exception, *value, *traceback; PyErr_Fetch( &exception, &value, &traceback ); PyErr_NormalizeException( &exception, &value, &traceback ); // Set sys. variables for exception tracking PySys_SetObject( "last_type", exception ); PySys_SetObject( "last_value", value ); PySys_SetObject( "last_traceback", traceback ); PyObject *exceptionName = PyObject_GetAttrString( exception, "__name__" ); // Do we have a detailed description of the error ? PyObject *error = value != 0 ? PyObject_Str( value ) : 0; if( !error ) { if( !moduleName.isNull() ) { Console::instance()->log( LOG_ERROR, QString( "An error occured while compiling \"%1\": %2" ).arg( moduleName ).arg( PyString_AsString( exceptionName ) ) ); } else { Console::instance()->log( LOG_ERROR, QString( "An error occured: %1" ).arg( PyString_AsString( exceptionName ) ) ); } } else { if( !moduleName.isNull() ) { Console::instance()->log( LOG_ERROR, QString( "An error occured in \"%1\": %2" ).arg( moduleName ).arg( PyString_AsString( exceptionName ) ) ); } else { Console::instance()->log( LOG_ERROR, QString( "An error occured: %1" ).arg( PyString_AsString( exceptionName ) ) ); } Console::instance()->log( LOG_PYTHON, QString( "%1: %2" ).arg( PyString_AsString( exceptionName ) ).arg( PyString_AsString( error ) ), false ); Py_XDECREF( error ); } // Don't print a traceback for syntax errors if( PyErr_GivenExceptionMatches( exception, PyExc_SyntaxError ) ) { Py_XDECREF( traceback ); traceback = 0; } // Dump a traceback while( traceback ) { if( !PyObject_HasAttrString( traceback, "tb_frame" ) ) break; PyObject *frame = PyObject_GetAttrString( traceback, "tb_frame" ); if( !PyObject_HasAttrString( frame, "f_code" ) ) { Py_XDECREF( frame ); break; } PyObject *code = PyObject_GetAttrString( frame, "f_code" ); if( !PyObject_HasAttrString( code, "co_filename" ) || !PyObject_HasAttrString( code, "co_name" ) ) { Py_XDECREF( frame ); Py_XDECREF( code ); break; } PyObject *pyFilename = PyObject_GetAttrString( code, "co_filename" ); PyObject *pyFunction = PyObject_GetAttrString( code, "co_name" ); QString filename = PyString_AsString( pyFilename ); QString function = PyString_AsString( pyFunction ); Py_XDECREF( pyFilename ); Py_XDECREF( pyFunction ); Py_XDECREF( code ); Py_XDECREF( frame ); PyObject *pyLine = PyObject_GetAttrString( traceback, "tb_lineno" ); unsigned int line = PyInt_AsLong( pyLine ); Py_XDECREF( pyLine ); // Print it Console::instance()->log( LOG_PYTHON, QString( "File '%1',%2 in '%3'" ).arg( filename ).arg( line ).arg( function ), false ); // Switch Frames PyObject *newtb = PyObject_GetAttrString( traceback, "tb_next" ); Py_XDECREF( traceback ); traceback = newtb; } Py_XDECREF( exceptionName ); Py_XDECREF( exception ); Py_XDECREF( value ); Py_XDECREF( traceback ); } }
/* 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; }
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 (!(current = get_current())) { goto error; } 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; }
/** * This emits the error signal and resets the error state * of the python interpreter. */ void PythonScript::emit_error() { // gil is necessary so other things don't continue ScopedPythonGIL lock; // return early if nothing happened if (!PyErr_Occurred()) { emit finished(MSG_FINISHED); return; } // get the error information out PyObject *exception(nullptr), *value(nullptr), *traceback(nullptr); PyErr_Fetch(&exception, &value, &traceback); // special check for system exceptions if (bool(exception) && PyErr_GivenExceptionMatches(exception, PyExc_SystemExit) && PyObject_HasAttrString(exception, "code")) { // value is the return code handed to sys.exit long code = 0; if (bool(value) && INT_CHECK(value)) { code = TO_LONG(value); } // if we are returning 0 then cleanup and return if (code == 0) { // maybe shouldn't clear the error, but for now this // is the agreed upon behavior PyErr_Clear(); Py_XDECREF(traceback); Py_XDECREF(exception); Py_XDECREF(value); emit finished(MSG_FINISHED); return; } } // prework on the exception handling PyErr_NormalizeException(&exception, &value, &traceback); PyErr_Clear(); // convert the traceback into something useful int lineNumber = 0; QString filename; if (traceback) { PyTracebackObject *tb = (PyTracebackObject *)traceback; lineNumber = tb->tb_lineno; filename = TO_CSTRING(tb->tb_frame->f_code->co_filename); } // the error message is the full (formated) traceback PyObject *str_repr = PyObject_Str(value); QString message; QTextStream msgStream(&message); if (value && str_repr) { if (exception == PyExc_SyntaxError) { msgStream << constructSyntaxErrorStr(value); } else { QString excTypeName( value->ob_type ->tp_name); // This is fully qualified with the module name excTypeName = excTypeName.section(".", -1); msgStream << excTypeName << ": " << TO_CSTRING(str_repr); } } else { msgStream << "Unknown exception has occurred."; } tracebackToMsg(msgStream, (PyTracebackObject *)(traceback)); msgStream << "\n"; Py_XDECREF(traceback); Py_XDECREF(exception); Py_XDECREF(value); emit error(msgStream.readAll(), filename, lineNumber); }
void PyErr_PrintEx(int set_sys_last_vars) { PyObject *exception, *v, *tb, *hook; if (PyErr_ExceptionMatches(PyExc_SystemExit)) { handle_system_exit(); } PyErr_Fetch(&exception, &v, &tb); if (exception == NULL) return; PyErr_NormalizeException(&exception, &v, &tb); if (exception == NULL) return; /* Now we know v != NULL too */ if (set_sys_last_vars) { PySys_SetObject("last_type", exception); PySys_SetObject("last_value", v); PySys_SetObject("last_traceback", tb); } hook = PySys_GetObject("excepthook"); if (hook) { PyObject *args = PyTuple_Pack(3, exception, v, tb ? tb : Py_None); PyObject *result = PyEval_CallObject(hook, args); if (result == NULL) { PyObject *exception2, *v2, *tb2; if (PyErr_ExceptionMatches(PyExc_SystemExit)) { handle_system_exit(); } PyErr_Fetch(&exception2, &v2, &tb2); PyErr_NormalizeException(&exception2, &v2, &tb2); /* It should not be possible for exception2 or v2 to be NULL. However PyErr_Display() can't tolerate NULLs, so just be safe. */ if (exception2 == NULL) { exception2 = Py_None; Py_INCREF(exception2); } if (v2 == NULL) { v2 = Py_None; Py_INCREF(v2); } if (Py_FlushLine()) PyErr_Clear(); fflush(stdout); PySys_WriteStderr("Error in sys.excepthook:\n"); PyErr_Display(exception2, v2, tb2); PySys_WriteStderr("\nOriginal exception was:\n"); PyErr_Display(exception, v, tb); Py_DECREF(exception2); Py_DECREF(v2); Py_XDECREF(tb2); } Py_XDECREF(result); Py_XDECREF(args); } else { PySys_WriteStderr("sys.excepthook is missing\n"); PyErr_Display(exception, v, tb); } Py_XDECREF(exception); Py_XDECREF(v); Py_XDECREF(tb); }
/* * Extract a Python traceback from the current exception. * * The exception error message is returned in xmsg, the traceback in * tbmsg (both as palloc'd strings) and the traceback depth in * tb_depth. */ static void PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth) { PyObject *e, *v, *tb; PyObject *e_type_o; PyObject *e_module_o; char *e_type_s = NULL; char *e_module_s = NULL; PyObject *vob = NULL; char *vstr; StringInfoData xstr; StringInfoData tbstr; /* * get the current exception */ PyErr_Fetch(&e, &v, &tb); /* * oops, no exception, return */ if (e == NULL) { *xmsg = NULL; *tbmsg = NULL; *tb_depth = 0; return; } PyErr_NormalizeException(&e, &v, &tb); /* * Format the exception and its value and put it in xmsg. */ e_type_o = PyObject_GetAttrString(e, "__name__"); e_module_o = PyObject_GetAttrString(e, "__module__"); if (e_type_o) e_type_s = PyString_AsString(e_type_o); if (e_type_s) e_module_s = PyString_AsString(e_module_o); if (v && ((vob = PyObject_Str(v)) != NULL)) vstr = PyString_AsString(vob); else vstr = "unknown"; initStringInfo(&xstr); if (!e_type_s || !e_module_s) { if (PyString_Check(e)) /* deprecated string exceptions */ appendStringInfoString(&xstr, PyString_AsString(e)); else /* shouldn't happen */ appendStringInfoString(&xstr, "unrecognized exception"); } /* mimics behavior of traceback.format_exception_only */ else if (strcmp(e_module_s, "builtins") == 0 || strcmp(e_module_s, "__main__") == 0 || strcmp(e_module_s, "exceptions") == 0) appendStringInfo(&xstr, "%s", e_type_s); else appendStringInfo(&xstr, "%s.%s", e_module_s, e_type_s); appendStringInfo(&xstr, ": %s", vstr); *xmsg = xstr.data; /* * Now format the traceback and put it in tbmsg. */ *tb_depth = 0; initStringInfo(&tbstr); /* Mimick Python traceback reporting as close as possible. */ appendStringInfoString(&tbstr, "Traceback (most recent call last):"); while (tb != NULL && tb != Py_None) { PyObject *volatile tb_prev = NULL; PyObject *volatile frame = NULL; PyObject *volatile code = NULL; PyObject *volatile name = NULL; PyObject *volatile lineno = NULL; PyObject *volatile filename = NULL; PG_TRY(); { lineno = PyObject_GetAttrString(tb, "tb_lineno"); if (lineno == NULL) elog(ERROR, "could not get line number from Python traceback"); frame = PyObject_GetAttrString(tb, "tb_frame"); if (frame == NULL) elog(ERROR, "could not get frame from Python traceback"); code = PyObject_GetAttrString(frame, "f_code"); if (code == NULL) elog(ERROR, "could not get code object from Python frame"); name = PyObject_GetAttrString(code, "co_name"); if (name == NULL) elog(ERROR, "could not get function name from Python code object"); filename = PyObject_GetAttrString(code, "co_filename"); if (filename == NULL) elog(ERROR, "could not get file name from Python code object"); } PG_CATCH(); { Py_XDECREF(frame); Py_XDECREF(code); Py_XDECREF(name); Py_XDECREF(lineno); Py_XDECREF(filename); PG_RE_THROW(); } PG_END_TRY(); /* The first frame always points at <module>, skip it. */ if (*tb_depth > 0) { PLyExecutionContext *exec_ctx = PLy_current_execution_context(); char *proname; char *fname; char *line; char *plain_filename; long plain_lineno; /* * The second frame points at the internal function, but to mimick * Python error reporting we want to say <module>. */ if (*tb_depth == 1) fname = "<module>"; else fname = PyString_AsString(name); proname = PLy_procedure_name(exec_ctx->curr_proc); plain_filename = PyString_AsString(filename); plain_lineno = PyInt_AsLong(lineno); if (proname == NULL) appendStringInfo( &tbstr, "\n PL/Python anonymous code block, line %ld, in %s", plain_lineno - 1, fname); else appendStringInfo( &tbstr, "\n PL/Python function \"%s\", line %ld, in %s", proname, plain_lineno - 1, fname); /* * function code object was compiled with "<string>" as the * filename */ if (exec_ctx->curr_proc && plain_filename != NULL && strcmp(plain_filename, "<string>") == 0) { /* * If we know the current procedure, append the exact line * from the source, again mimicking Python's traceback.py * module behavior. We could store the already line-split * source to avoid splitting it every time, but producing a * traceback is not the most important scenario to optimize * for. But we do not go as far as traceback.py in reading * the source of imported modules. */ line = get_source_line(exec_ctx->curr_proc->src, plain_lineno); if (line) { appendStringInfo(&tbstr, "\n %s", line); pfree(line); } } } Py_DECREF(frame); Py_DECREF(code); Py_DECREF(name); Py_DECREF(lineno); Py_DECREF(filename); /* Release the current frame and go to the next one. */ tb_prev = tb; tb = PyObject_GetAttrString(tb, "tb_next"); Assert(tb_prev != Py_None); Py_DECREF(tb_prev); if (tb == NULL) elog(ERROR, "could not traverse Python traceback"); (*tb_depth)++; } /* Return the traceback. */ *tbmsg = tbstr.data; Py_XDECREF(e_type_o); Py_XDECREF(e_module_o); Py_XDECREF(vob); Py_XDECREF(v); Py_DECREF(e); }
ErrorResult PythonEngine::parseError() { QString traceback; QString text; int line = -1; PyErr_NormalizeException(&errorType, &errorValue, &errorTraceback); if (errorTraceback) { PyTracebackObject *tb = (PyTracebackObject *) errorTraceback; line = tb->tb_lineno; text.append(QString("Line %1: ").arg(tb->tb_lineno)); while (tb) { PyFrameObject *frame = tb->tb_frame; if (frame && frame->f_code) { PyCodeObject* codeObject = frame->f_code; if (PyString_Check(codeObject->co_filename)) traceback.append(QString("File '%1'").arg(PyString_AsString(codeObject->co_filename))); int errorLine = PyCode_Addr2Line(codeObject, frame->f_lasti); traceback.append(QString(", line %1").arg(errorLine)); if (PyString_Check(codeObject->co_name)) traceback.append(QString(", in %1").arg(PyString_AsString(codeObject->co_name))); } traceback.append(QString("\n")); tb = tb->tb_next; } } traceback = traceback.trimmed(); PyObject *errorString = NULL; if (errorType != NULL && (errorString = PyObject_Str(errorType)) != NULL && (PyString_Check(errorString))) { Py_INCREF(errorString); text.append(PyString_AsString(errorString)); Py_XDECREF(errorString); } else { text.append("\n<unknown exception type>"); } if (errorValue != NULL && (errorString = PyObject_Str(errorValue)) != NULL && (PyString_Check(errorString))) { Py_INCREF(errorString); text.append("\n"); text.append(PyString_AsString(errorString)); Py_XDECREF(errorString); } else { text.append("\n<unknown exception data>"); } Py_XDECREF(errorType); errorType = NULL; Py_XDECREF(errorValue); errorValue = NULL; Py_XDECREF(errorTraceback); errorTraceback = NULL; PyErr_Clear(); return ErrorResult(text, traceback, line); }
QString QgsPythonUtilsImpl::getTraceback() { #define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;} // acquire global interpreter lock to ensure we are in a consistent state PyGILState_STATE gstate; gstate = PyGILState_Ensure(); QString errMsg; QString result; PyObject *modStringIO = NULL; PyObject *modTB = NULL; PyObject *obStringIO = NULL; PyObject *obResult = NULL; PyObject *type, *value, *traceback; PyErr_Fetch( &type, &value, &traceback ); PyErr_NormalizeException( &type, &value, &traceback ); modStringIO = PyImport_ImportModule( "cStringIO" ); if ( modStringIO == NULL ) TRACEBACK_FETCH_ERROR( "can't import cStringIO" ); obStringIO = PyObject_CallMethod( modStringIO, ( char* ) "StringIO", NULL ); /* Construct a cStringIO object */ if ( obStringIO == NULL ) TRACEBACK_FETCH_ERROR( "cStringIO.StringIO() failed" ); modTB = PyImport_ImportModule( "traceback" ); if ( modTB == NULL ) TRACEBACK_FETCH_ERROR( "can't import traceback" ); obResult = PyObject_CallMethod( modTB, ( char* ) "print_exception", ( char* ) "OOOOO", type, value ? value : Py_None, traceback ? traceback : Py_None, Py_None, obStringIO ); if ( obResult == NULL ) TRACEBACK_FETCH_ERROR( "traceback.print_exception() failed" ); Py_DECREF( obResult ); obResult = PyObject_CallMethod( obStringIO, ( char* ) "getvalue", NULL ); if ( obResult == NULL ) TRACEBACK_FETCH_ERROR( "getvalue() failed." ); /* And it should be a string all ready to go - duplicate it. */ if ( !PyString_Check( obResult ) ) TRACEBACK_FETCH_ERROR( "getvalue() did not return a string" ); result = PyString_AsString( obResult ); done: // All finished - first see if we encountered an error if ( result.isEmpty() && !errMsg.isEmpty() ) { result = errMsg; } Py_XDECREF( modStringIO ); Py_XDECREF( modTB ); Py_XDECREF( obStringIO ); Py_XDECREF( obResult ); Py_XDECREF( value ); Py_XDECREF( traceback ); Py_XDECREF( type ); // we are done calling python API, release global interpreter lock PyGILState_Release( gstate ); return result; }
static PyObject * gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing) { PyThreadState *tstate = PyThreadState_GET(); PyFrameObject *f = gen->gi_frame; PyObject *result; if (gen->gi_running) { char *msg = "generator already executing"; if (PyCoro_CheckExact(gen)) msg = "coroutine already executing"; PyErr_SetString(PyExc_ValueError, msg); return NULL; } if (f == NULL || f->f_stacktop == NULL) { if (PyCoro_CheckExact(gen) && !closing) { /* `gen` is an exhausted coroutine: raise an error, except when called from gen_close(), which should always be a silent method. */ PyErr_SetString( PyExc_RuntimeError, "cannot reuse already awaited coroutine"); } else if (arg && !exc) { /* `gen` is an exhausted generator: only set exception if called from send(). */ PyErr_SetNone(PyExc_StopIteration); } return NULL; } if (f->f_lasti == -1) { if (arg && arg != Py_None) { char *msg = "can't send non-None value to a " "just-started generator"; if (PyCoro_CheckExact(gen)) msg = "can't send non-None value to a " "just-started coroutine"; PyErr_SetString(PyExc_TypeError, msg); return NULL; } } else { /* Push arg onto the frame's value stack */ result = arg ? arg : Py_None; Py_INCREF(result); *(f->f_stacktop++) = result; } /* Generators always return to their most recent caller, not * necessarily their creator. */ Py_XINCREF(tstate->frame); assert(f->f_back == NULL); f->f_back = tstate->frame; gen->gi_running = 1; result = PyEval_EvalFrameEx(f, exc); gen->gi_running = 0; /* Don't keep the reference to f_back any longer than necessary. It * may keep a chain of frames alive or it could create a reference * cycle. */ assert(f->f_back == tstate->frame); Py_CLEAR(f->f_back); /* If the generator just returned (as opposed to yielding), signal * that the generator is exhausted. */ if (result && f->f_stacktop == NULL) { if (result == Py_None) { /* Delay exception instantiation if we can */ PyErr_SetNone(PyExc_StopIteration); } else { PyObject *e = PyObject_CallFunctionObjArgs( PyExc_StopIteration, result, NULL); if (e != NULL) { PyErr_SetObject(PyExc_StopIteration, e); Py_DECREF(e); } } Py_CLEAR(result); } else if (!result && PyErr_ExceptionMatches(PyExc_StopIteration)) { /* Check for __future__ generator_stop and conditionally turn * a leaking StopIteration into RuntimeError (with its cause * set appropriately). */ if (((PyCodeObject *)gen->gi_code)->co_flags & (CO_FUTURE_GENERATOR_STOP | CO_COROUTINE | CO_ITERABLE_COROUTINE)) { PyObject *exc, *val, *val2, *tb; char *msg = "generator raised StopIteration"; if (PyCoro_CheckExact(gen)) msg = "coroutine raised StopIteration"; PyErr_Fetch(&exc, &val, &tb); PyErr_NormalizeException(&exc, &val, &tb); if (tb != NULL) PyException_SetTraceback(val, tb); Py_DECREF(exc); Py_XDECREF(tb); PyErr_SetString(PyExc_RuntimeError, msg); PyErr_Fetch(&exc, &val2, &tb); PyErr_NormalizeException(&exc, &val2, &tb); Py_INCREF(val); PyException_SetCause(val2, val); PyException_SetContext(val2, val); PyErr_Restore(exc, val2, tb); } else { PyObject *exc, *val, *tb; /* Pop the exception before issuing a warning. */ PyErr_Fetch(&exc, &val, &tb); if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "generator '%.50S' raised StopIteration", gen->gi_qualname)) { /* Warning was converted to an error. */ Py_XDECREF(exc); Py_XDECREF(val); Py_XDECREF(tb); } else { PyErr_Restore(exc, val, tb); } } } if (!result || f->f_stacktop == NULL) { /* generator can't be rerun, so release the frame */ /* first clean reference cycle through stored exception traceback */ PyObject *t, *v, *tb; t = f->f_exc_type; v = f->f_exc_value; tb = f->f_exc_traceback; f->f_exc_type = NULL; f->f_exc_value = NULL; f->f_exc_traceback = NULL; Py_XDECREF(t); Py_XDECREF(v); Py_XDECREF(tb); gen->gi_frame->f_gen = NULL; gen->gi_frame = NULL; Py_DECREF(f); } return result; }
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); } }
static gboolean glade_python_setup () { GString *command; const gchar *module_path; const GList *paths; Py_SetProgramName (PY_STRING (PACKAGE_NAME)); /* Initialize the Python interpreter */ python_init (); /* Check and init pygobject */ PyErr_Clear (); glade_python_init_pygobject_check (PYGOBJECT_REQUIRED_MAJOR, PYGOBJECT_REQUIRED_MINOR, PYGOBJECT_REQUIRED_MICRO); if (PyErr_Occurred ()) { PyObject *ptype, *pvalue, *ptraceback, *pstr; char *pvalue_char = ""; PyErr_Fetch (&ptype, &pvalue, &ptraceback); PyErr_NormalizeException (&ptype, &pvalue, &ptraceback); if ((pstr = PyObject_Str (pvalue))) pvalue_char = STRING_FROM_PYSTR (pstr); g_warning ("Unable to load pygobject module >= %d.%d.%d, " "please make sure it is in python's path (sys.path). " "(use PYTHONPATH env variable to specify non default paths)\n%s", PYGOBJECT_REQUIRED_MAJOR, PYGOBJECT_REQUIRED_MINOR, PYGOBJECT_REQUIRED_MICRO, pvalue_char); Py_DecRef (ptype); Py_DecRef (pvalue); Py_DecRef (ptraceback); Py_DecRef (pstr); PyErr_Clear (); Py_Finalize (); return TRUE; } pyg_disable_warning_redirections (); /* Generate system path array */ command = g_string_new ("import sys; sys.path+=["); /* GLADE_ENV_MODULE_PATH has priority */ module_path = g_getenv (GLADE_ENV_MODULE_PATH); if (module_path) g_string_append_printf (command, "'%s', ", module_path); /* Append modules directory */ g_string_append_printf (command, "'%s'", glade_app_get_modules_dir ()); /* Append extra paths (declared in the Preferences) */ for (paths = glade_catalog_get_extra_paths (); paths; paths = g_list_next (paths)) g_string_append_printf (command, ", '%s'", (gchar *) paths->data); /* Close python statement */ g_string_append (command, "];\n"); /* Make sure we load Gtk 3 */ g_string_append (command, "import gi; gi.require_version('Gtk', '3.0');\n"); /* Finally run statement in vm */ PyRun_SimpleString (command->str); g_string_free (command, TRUE); return FALSE; }
// Format the current Python exception as a string. // Let Python do the work for us; call traceback.format_exception() std::string formatPythonException() { if (!PyErr_Occurred()) { return "<no error?>"; } // Retrieve Python exception and "normalize" (the docs are unclear but // they say you should do it :) ) PyObject* exceptionObj; PyObject* valueObj; PyObject* tracebackObj; PyErr_Fetch(&exceptionObj, &valueObj, &tracebackObj); DCHECK(exceptionObj); PyErr_NormalizeException(&exceptionObj, &valueObj, &tracebackObj); PyObjectHandle exception(exceptionObj); PyObjectHandle value(valueObj); PyObjectHandle traceback(tracebackObj); // value and traceback may be null if (!value) { value.reset(PyObjectHandle::INCREF, Py_None); } if (!traceback) { traceback.reset(PyObjectHandle::INCREF, Py_None); } PyObjectHandle tbModule(PyImport_ImportModule("traceback")); if (!tbModule) { return "<import traceback failed>"; } PyObject* tbDict = PyModule_GetDict(tbModule.get()); // borrowed if (!tbDict) { return "<no dict in traceback module>"; } // borrowed PyObject* formatFunc = PyDict_GetItemString(tbDict, "format_exception"); if (!formatFunc) { return "<no format_exception in traceback module>"; } PyObjectHandle formatted(PyObject_CallFunction( formatFunc, const_cast<char*>("OOO"), exception.get(), value.get(), traceback.get())); if (!formatted) { return "<traceback.format_exception error>"; } // format_exception returns a list of strings that should be concatenated. // Well then, let's do that. if (!PyList_Check(formatted.get())) { return "<traceback.format_exception didn't return a list>"; } std::string out; for (Py_ssize_t i = 0; i < PyList_GET_SIZE(formatted.get()); ++i) { PyObject* obj = PyList_GET_ITEM(formatted.get(), i); // borrowed char* data; Py_ssize_t len; if (PyString_AsStringAndSize(obj, &data, &len) == -1) { return "<traceback.format_exception member not a string>"; } out.append(data, len); } return out; }
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 #if PY_VERSION_HEX >= 0x030700A2 tmp_type = tstate->exc_state.exc_type; tmp_value = tstate->exc_state.exc_value; tmp_tb = tstate->exc_state.exc_traceback; tstate->exc_state.exc_type = local_type; tstate->exc_state.exc_value = local_value; tstate->exc_state.exc_traceback = local_tb; #else 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; #endif // 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; }
static char * get_exc_trace() { char *tbstr = NULL; PyObject *iostrmod = NULL; PyObject *tbmod = NULL; PyObject *iostr = NULL; PyObject *obstr = NULL; PyObject *args = NULL; PyObject *newstr = NULL; PyObject *func = NULL; char* rv = NULL; PyObject *type, *value, *traceback; TARGET_THREAD_BEGIN_BLOCK; PyErr_Fetch(&type, &value, &traceback); debug("** type %p, value %p, traceback %p", type, value, traceback); PyErr_Print(); PyErr_Clear(); PyErr_NormalizeException(&type, &value, &traceback); debug("** type %p, value %p, traceback %p", type, value, traceback); iostrmod = PyImport_ImportModule("StringIO"); if (iostrmod==NULL) TB_ERROR("can't import StringIO"); iostr = PyObject_CallMethod(iostrmod, "StringIO", NULL); if (iostr==NULL) TB_ERROR("cStringIO.StringIO() failed"); tbmod = PyImport_ImportModule("traceback"); if (tbmod==NULL) TB_ERROR("can't import traceback"); obstr = PyObject_CallMethod(tbmod, "print_exception", "(OOOOO)", type ? type : Py_None, value ? value : Py_None, traceback ? traceback : Py_None, Py_None, iostr); if (obstr==NULL) { PyErr_Print(); TB_ERROR("traceback.print_exception() failed"); } Py_DecRef(obstr); obstr = PyObject_CallMethod(iostr, "getvalue", NULL); if (obstr==NULL) TB_ERROR("getvalue() failed."); if (!PyString_Check(obstr)) TB_ERROR("getvalue() did not return a string"); debug("%s", PyString_AsString(obstr)); args = PyTuple_New(2); PyTuple_SetItem(args, 0, string2target("\n")); PyTuple_SetItem(args, 1, string2target("<br>")); func = PyObject_GetAttrString(obstr, "replace"); //newstr = PyObject_CallMethod(obstr, "replace", args); newstr = PyObject_CallObject(func, args); tbstr = PyString_AsString(newstr); rv = fmtstr("plugin:%s", tbstr); cleanup: PyErr_Restore(type, value, traceback); if (rv == NULL) { rv = tbstr ? tbstr : ""; } Py_DecRef(func); Py_DecRef(args); Py_DecRef(newstr); Py_DecRef(iostr); Py_DecRef(obstr); Py_DecRef(iostrmod); Py_DecRef(tbmod); TARGET_THREAD_END_BLOCK; return rv; }