- ename = "(unknown exception)";
-
- /* Send the exception error message(s) to srd_err(). */
- py_str_as_str(py_str, &str);
- g_string_append(msg, ename);
- g_string_append(msg, ": ");
- g_string_append(msg, str);
- Py_DecRef(py_str);
- srd_err(msg->str);
-
- /* Send a more precise error location to srd_dbg(), if we have it. */
- if (etb && etb != Py_None) {
- tracestr = NULL;
- py_tb = (PyTracebackObject *) etb;
- py_str = PyUnicode_FromFormat("%U:%d in %U",
- py_tb->tb_frame->f_code->co_filename, py_tb->tb_frame->f_lineno,
- py_tb->tb_frame->f_code->co_name);
- py_str_as_str(py_str, &tracestr);
- Py_DecRef(py_str);
- g_string_printf(msg, "srd: %s in %s: %s", ename,
- tracestr, str);
- srd_dbg(msg->str);
- g_free(tracestr);
+ srd_err("%s: %s.", etype_name_fallback, msg);
+
+ g_free(evalue_str);
+ g_free(etype_name);
+
+ /* If there is no traceback object, we are done. */
+ if (!py_etraceback)
+ goto cleanup;
+
+ py_mod = py_import_by_name("traceback");
+ if (!py_mod)
+ goto cleanup;
+
+ py_func = PyObject_GetAttrString(py_mod, "format_exception");
+ if (!py_func || !PyCallable_Check(py_func))
+ goto cleanup;
+
+ /* Call into Python to format the stack trace. */
+ py_tracefmt = PyObject_CallFunctionObjArgs(py_func,
+ py_etype, py_evalue, py_etraceback, NULL);
+ if (!py_tracefmt || !PyList_Check(py_tracefmt))
+ goto cleanup;
+
+ 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);
+ }