[icinga-checkins] icinga.org: icinga2/master: Print backtrace for Python exceptions.

git at icinga.org git at icinga.org
Sat Feb 16 11:31:19 CET 2013


Module: icinga2
Branch: master
Commit: d0f263abb1f7dda3246121b3961766061123f997
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=d0f263abb1f7dda3246121b3961766061123f997

Author: Gunnar Beutner <gunnar.beutner at netways.de>
Date:   Sat Feb 16 11:28:34 2013 +0100

Print backtrace for Python exceptions.

---

 lib/python/pythoninterpreter.cpp |   14 +++++---------
 lib/python/pythonlanguage.cpp    |   28 ++++++++++++++++++++++++++++
 lib/python/pythonlanguage.h      |    2 ++
 3 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/lib/python/pythoninterpreter.cpp b/lib/python/pythoninterpreter.cpp
index ea66519..ba1cc5d 100644
--- a/lib/python/pythoninterpreter.cpp
+++ b/lib/python/pythoninterpreter.cpp
@@ -98,18 +98,14 @@ void PythonInterpreter::ProcessCall(const ScriptTask::Ptr& task, const String& f
 			PyObject *ptype, *pvalue, *ptraceback;
 
 			PyErr_Fetch(&ptype, &pvalue, &ptraceback);
-			PyObject *pstr_msg = PyObject_Str(pvalue);
-			PyObject *pstr_tb = PyObject_Str(ptraceback);
-			Py_DECREF(pvalue);
-			PyErr_Clear();
 
-			String msg = PyString_AsString(pstr_msg);
-			Py_DECREF(pstr_msg);
+			String msg = m_Language->ExceptionInfoToString(ptype, pvalue, ptraceback);
 
-			String tb = PyString_AsString(pstr_tb);
-			Py_DECREF(pstr_tb);
+			Py_XDECREF(ptype);
+			Py_XDECREF(pvalue);
+			Py_XDECREF(ptraceback);
 
-			BOOST_THROW_EXCEPTION(runtime_error("Error in Python script:" + msg + " at " + tb));
+			BOOST_THROW_EXCEPTION(runtime_error("Error in Python script:" + msg));
 		}
 
 		Value vresult = PythonLanguage::MarshalFromPython(result);
diff --git a/lib/python/pythonlanguage.cpp b/lib/python/pythonlanguage.cpp
index e51a941..d5b832e 100644
--- a/lib/python/pythonlanguage.cpp
+++ b/lib/python/pythonlanguage.cpp
@@ -44,6 +44,8 @@ PythonLanguage::PythonLanguage(void)
 
 	m_MainThreadState = PyThreadState_Get();
 
+	m_TracebackModule = PyImport_ImportModule("traceback");
+
 	m_NativeModule = Py_InitModule("ire", m_NativeMethodDef);
 
 	(void) PyThreadState_Swap(NULL);
@@ -200,6 +202,32 @@ Value PythonLanguage::MarshalFromPython(PyObject *value)
 	}
 }
 
+String PythonLanguage::ExceptionInfoToString(PyObject *type, PyObject *exc, PyObject *tb) const
+{
+	PyObject *tb_dict = PyModule_GetDict(m_TracebackModule);
+	PyObject *format_exception = PyDict_GetItemString(tb_dict, "format_exception");
+
+	if (!PyCallable_Check(format_exception))
+		return "Failed to format exception information.";
+
+	PyObject *result = PyObject_CallFunctionObjArgs(format_exception, type, exc, tb);
+
+	Py_DECREF(format_exception);
+	Py_DECREF(tb_dict);
+
+	if (!result || !PyString_Check(result)) {
+		Py_XDECREF(result);
+
+		return "format_exception() returned something that is not a string.";
+	}
+
+	String msg = PyString_AsString(result);
+
+	Py_DECREF(result);
+
+	return msg;
+}
+
 PyObject *PythonLanguage::PyCallNativeFunction(PyObject *self, PyObject *args)
 {
 	assert(PyString_Check(self));
diff --git a/lib/python/pythonlanguage.h b/lib/python/pythonlanguage.h
index feea67c..099c0e4 100644
--- a/lib/python/pythonlanguage.h
+++ b/lib/python/pythonlanguage.h
@@ -49,9 +49,11 @@ public:
 	static PyObject *MarshalToPython(const Value& value);
 	static Value MarshalFromPython(PyObject *value);
 
+	String ExceptionInfoToString(PyObject *type, PyObject *exc, PyObject *tb) const;
 private:
 	PyThreadState *m_MainThreadState;
 	PyObject *m_NativeModule;
+	PyObject *m_TracebackModule;
 	static PythonInterpreter *m_CurrentInterpreter;
 
 	void RegisterNativeFunction(const String& name, const ScriptFunction::Ptr& function);





More information about the icinga-checkins mailing list