X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=exception.c;h=9f8ee4ceb17b028179446b786d53ce318b7fbfb8;hp=a2b2683cc347087379e49881821389208acfb027;hb=a27981c145cd9a3709673339dc455f3a0d5c3745;hpb=201a85a8ea071d37f4fda2668c0a1c488d852f4e diff --git a/exception.c b/exception.c index a2b2683..9f8ee4c 100644 --- a/exception.c +++ b/exception.c @@ -28,6 +28,8 @@ static char *py_stringify(PyObject *py_obj) PyObject *py_str, *py_bytes; char *str = NULL; + /* Note: Caller already ran PyGILState_Ensure(). */ + if (!py_obj) return NULL; @@ -48,6 +50,7 @@ cleanup: PyErr_Clear(); srd_dbg("Failed to stringify object."); } + return str; } @@ -56,6 +59,8 @@ static char *py_get_string_attr(PyObject *py_obj, const char *attr) PyObject *py_str, *py_bytes; char *str = NULL; + /* Note: Caller already ran PyGILState_Ensure(). */ + if (!py_obj) return NULL; @@ -76,17 +81,21 @@ cleanup: PyErr_Clear(); srd_dbg("Failed to get object attribute %s.", attr); } + return str; } /** @private */ SRD_PRIV void srd_exception_catch(const char *format, ...) { + int i, ret; va_list args; PyObject *py_etype, *py_evalue, *py_etraceback; - PyObject *py_modname, *py_mod, *py_func, *py_tracefmt; - char *msg, *etype_name, *evalue_str, *tracefmt_str; + PyObject *py_mod, *py_func, *py_tracefmt; + char *msg, *etype_name, *evalue_str, *outstr; const char *etype_name_fallback; + PyGILState_STATE gstate; + GString *s; py_etype = py_evalue = py_etraceback = py_mod = py_func = NULL; @@ -94,6 +103,8 @@ SRD_PRIV void srd_exception_catch(const char *format, ...) msg = g_strdup_vprintf(format, args); va_end(args); + gstate = PyGILState_Ensure(); + PyErr_Fetch(&py_etype, &py_evalue, &py_etraceback); if (!py_etype) { /* No current exception, so just print the message. */ @@ -118,13 +129,7 @@ SRD_PRIV void srd_exception_catch(const char *format, ...) if (!py_etraceback) goto cleanup; - py_modname = PyUnicode_FromString("traceback"); - if (!py_modname) - goto cleanup; - - py_mod = PyImport_Import(py_modname); - Py_DECREF(py_modname); - + py_mod = py_import_by_name("traceback"); if (!py_mod) goto cleanup; @@ -135,17 +140,21 @@ SRD_PRIV void srd_exception_catch(const char *format, ...) /* Call into Python to format the stack trace. */ py_tracefmt = PyObject_CallFunctionObjArgs(py_func, py_etype, py_evalue, py_etraceback, NULL); - if (!py_tracefmt) + if (!py_tracefmt || !PyList_Check(py_tracefmt)) goto cleanup; - tracefmt_str = py_stringify(py_tracefmt); - Py_DECREF(py_tracefmt); - - /* Log the detailed stack trace. */ - if (tracefmt_str) { - srd_dbg("%s", tracefmt_str); - g_free(tracefmt_str); + s = g_string_sized_new(128); + for (i = 0; i < PyList_Size(py_tracefmt); i++) { + ret = py_listitem_as_str(py_tracefmt, i, &outstr); + if (ret == 0) { + s = g_string_append(s, outstr); + g_free(outstr); + } } + srd_err("%s", s->str); + g_string_free(s, TRUE); + + Py_DECREF(py_tracefmt); cleanup: Py_XDECREF(py_func); @@ -157,5 +166,7 @@ cleanup: /* Just in case. */ PyErr_Clear(); + PyGILState_Release(gstate); + g_free(msg); }