]> sigrok.org Git - libsigrokdecode.git/blobdiff - exception.c
cfp: Fix incorrect copy-paste description.
[libsigrokdecode.git] / exception.c
index 7027df5abcdf65b8269323113e1809193ea4b085..9f8ee4ceb17b028179446b786d53ce318b7fbfb8 100644 (file)
@@ -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_mod, *py_func, *py_tracefmt;
-       char *msg, *etype_name, *evalue_str, *tracefmt_str;
+       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. */
@@ -129,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);
@@ -151,5 +166,7 @@ cleanup:
        /* Just in case. */
        PyErr_Clear();
 
+       PyGILState_Release(gstate);
+
        g_free(msg);
 }