]> granicus.if.org Git - icinga2/commitdiff
Print backtrace for Python exceptions.
authorGunnar Beutner <gunnar.beutner@netways.de>
Sat, 16 Feb 2013 10:28:34 +0000 (11:28 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sat, 16 Feb 2013 10:28:34 +0000 (11:28 +0100)
lib/python/pythoninterpreter.cpp
lib/python/pythonlanguage.cpp
lib/python/pythonlanguage.h

index ea665190ccb7405f41b68dd494b70bb93e3e30be..ba1cc5dc477e85f6f04c60eb254f26500f03d37f 100644 (file)
@@ -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);
index e51a9415a582078c16127badcda5c2af2157b104..d5b832e9fd402b3260db7ab9be102187d69a97bf 100644 (file)
@@ -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));
index feea67cbf91efb247f15f7be0799cc1120bfc3b5..099c0e47d10cde1fe3d2682d9fdc9ae33b0ea419 100644 (file)
@@ -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);