Author: aconway
Date: Thu Jun 12 13:46:43 2014
New Revision: 1602161
URL: http://svn.apache.org/r1602161
Log:
DISPATCH-16: Integrated python error handling with dispatch logging and error
handling.
See error.h, new function qd_error_py(). Checks for python error, logs python
stack
trace and sets qd_error() indicators.
Modified:
qpid/dispatch/trunk/include/qpid/dispatch/error.h
qpid/dispatch/trunk/src/config.c
qpid/dispatch/trunk/src/error.c
qpid/dispatch/trunk/src/log.c
qpid/dispatch/trunk/src/log_private.h
qpid/dispatch/trunk/src/python_embedded.c
qpid/dispatch/trunk/src/router_pynode.c
Modified: qpid/dispatch/trunk/include/qpid/dispatch/error.h
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch/error.h?rev=1602161&r1=1602160&r2=1602161&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch/error.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch/error.h Thu Jun 12 13:46:43 2014
@@ -40,6 +40,7 @@ typedef enum {
QD_ERROR_ALREADY_EXISTS,
QD_ERROR_ALLOC,
QD_ERROR_MESSAGE, ///< Error parsing a message.
+ QD_ERROR_PYTHON, ///< Error from python code.
QD_ERROR_COUNT ///< Not an error, marks the end of the enum
} qd_error_t;
@@ -69,4 +70,17 @@ qd_error_t qd_error_code();
/** Maximum length of a qd_error_message, useful for temporary buffers. */
extern const int QD_ERROR_MAX;
+
+/**
+ * Check for a python error.
+ *
+ * If there is a python error, call qd_error(QD_ERROR_PYTHON, <python-msg>),
+ * clear the python error indicator, log the python error and stack trace and
+ * return QD_ERROR_PYTHON.
+ *
+ * If there is no python error, call qd_error_clear() and return QD_ERROR_NONE.
+ *
+ * @return QD_ERROR_PYTHON or QD_ERROR_NONE.
+ */
+qd_error_t qd_error_py();
#endif
Modified: qpid/dispatch/trunk/src/config.c
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/config.c?rev=1602161&r1=1602160&r2=1602161&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/config.c (original)
+++ qpid/dispatch/trunk/src/config.c Thu Jun 12 13:46:43 2014
@@ -60,7 +60,7 @@ qd_config_t *qd_config(void)
Py_DECREF(pName);
if (!config->pModule) {
- PyErr_Print();
+ qd_error_py();
free_qd_config_t(config);
qd_log(log_source, QD_LOG_ERROR, "Unable to load configuration module:
%s", PYTHON_MODULE);
return 0;
@@ -83,7 +83,7 @@ qd_config_t *qd_config(void)
Py_DECREF(pArgs);
if (config->pObject == 0) {
- PyErr_Print();
+ qd_error_py();
Py_DECREF(config->pModule);
free_qd_config_t(config);
return 0;
@@ -120,9 +120,7 @@ void qd_config_read(qd_config_t *config,
if (pResult) {
Py_DECREF(pResult);
} else {
-#ifndef NDEBUG
- PyErr_Print();
-#endif
+ qd_error_py();
qd_log(log_source, QD_LOG_CRITICAL, "Configuration Failed, Exiting");
exit(1);
}
@@ -280,4 +278,3 @@ int qd_config_item_value_bool(const qd_d
return value;
}
-
Modified: qpid/dispatch/trunk/src/error.c
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/error.c?rev=1602161&r1=1602160&r2=1602161&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/error.c (original)
+++ qpid/dispatch/trunk/src/error.c Thu Jun 12 13:46:43 2014
@@ -17,6 +17,7 @@
* under the License.
*/
+#include <Python.h>
#include <qpid/dispatch/error.h>
#include <qpid/dispatch/log.h>
#include <stdarg.h>
@@ -29,7 +30,8 @@ static const char *error_names[] = {
"Not found",
"Already exists",
"Allocation",
- "Invalid message"
+ "Invalid message",
+ "Python"
};
STATIC_ASSERT(sizeof(error_names)/sizeof(error_names[0]) == QD_ERROR_COUNT,
error_names_wrong_size);
@@ -56,7 +58,7 @@ qd_error_t qd_error(qd_error_t code, con
va_start(arglist, fmt);
vsnprintf(error_message+i, ERROR_MAX-i, fmt, arglist);
va_end(arglist);
- qd_log(log_source, QD_LOG_TRACE, "%s", qd_error_message());
+ qd_log(log_source, QD_LOG_ERROR, "%s", qd_error_message());
return code;
}
else
@@ -76,3 +78,63 @@ const char* qd_error_message() {
qd_error_t qd_error_code() {
return error_code;
}
+
+static void py_set_item(PyObject *dict, const char* name, PyObject *value) {
+ PyObject *py_name = PyString_FromString(name);
+ PyDict_SetItem(dict, py_name, value);
+ Py_DECREF(py_name);
+}
+
+static PyObject *py_import(const char* module) {
+ PyObject *py_str = PyString_FromString(module);
+ PyObject *py_module = PyImport_Import(py_str);
+ Py_DECREF(py_str);
+ return py_module;
+}
+
+static void log_trace_py(PyObject *type, PyObject *value, PyObject* trace) {
+ if (!(type && value && trace)) return;
+
+ PyObject *module = py_import("traceback");
+ if (!module) return;
+
+ PyObject *globals = PyDict_New();
+ py_set_item(globals, "traceback", module);
+ Py_DECREF(module);
+
+ PyObject *locals = PyDict_New();
+ py_set_item(locals, "type", type);
+ py_set_item(locals, "value", value);
+ py_set_item(locals, "trace", trace);
+
+ PyObject *result = PyRun_String(
+ "'\\n'.join(traceback.format_exception(type, value, trace))",
Py_eval_input, globals, locals);
+ Py_DECREF(globals);
+ Py_DECREF(locals);
+
+ if (result) {
+ qd_log(log_source, QD_LOG_ERROR, "%s", PyString_AsString(result));
+ Py_DECREF(result);
+ }
+}
+
+qd_error_t qd_error_py() {
+ if (PyErr_Occurred()) {
+ PyObject *type, *value, *trace;
+ PyErr_Fetch(&type, &value, &trace); /* Note clears the python error
indicator */
+
+ PyObject *py_str = value ? PyObject_Str(value) : NULL;
+ const char* str = py_str ? PyString_AsString(py_str) : NULL;
+ qd_error(QD_ERROR_PYTHON, "%s", str ? str : "Unknown");
+ Py_XDECREF(py_str);
+
+ log_trace_py(type, value, trace);
+
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(trace);
+ } else {
+ qd_error_clear();
+ }
+ return qd_error_code();
+}
Modified: qpid/dispatch/trunk/src/log.c
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/log.c?rev=1602161&r1=1602160&r2=1602161&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/log.c (original)
+++ qpid/dispatch/trunk/src/log.c Thu Jun 12 13:46:43 2014
@@ -31,8 +31,8 @@
#include <syslog.h>
#define TEXT_MAX QD_LOG_TEXT_MAX
+#define LOG_MAX (QD_LOG_TEXT_MAX+128)
#define LIST_MAX 1000
-#define LOG_MAX 640
static qd_log_source_t *default_log_source=0;
static qd_log_source_t *logging_log_source=0;
Modified: qpid/dispatch/trunk/src/log_private.h
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/log_private.h?rev=1602161&r1=1602160&r2=1602161&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/log_private.h (original)
+++ qpid/dispatch/trunk/src/log_private.h Thu Jun 12 13:46:43 2014
@@ -23,5 +23,5 @@
void qd_log_initialize(void);
void qd_log_finalize(void);
-#define QD_LOG_TEXT_MAX 512
+#define QD_LOG_TEXT_MAX 1024
#endif
Modified: qpid/dispatch/trunk/src/python_embedded.c
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/python_embedded.c?rev=1602161&r1=1602160&r2=1602161&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/python_embedded.c (original)
+++ qpid/dispatch/trunk/src/python_embedded.c Thu Jun 12 13:46:43 2014
@@ -20,6 +20,7 @@
#include <qpid/dispatch/python_embedded.h>
#include <qpid/dispatch/threading.h>
#include <qpid/dispatch/log.h>
+#include <qpid/dispatch/error.h>
#include <qpid/dispatch/amqp.h>
#include <qpid/dispatch/alloc.h>
#include <qpid/dispatch/router.h>
@@ -645,7 +646,7 @@ static void qd_python_setup(void)
LogAdapterType.tp_new = PyType_GenericNew;
IoAdapterType.tp_new = PyType_GenericNew;
if ((PyType_Ready(&LogAdapterType) < 0) || (PyType_Ready(&IoAdapterType) <
0)) {
- PyErr_Print();
+ qd_error_py();
qd_log(log_source, QD_LOG_ERROR, "Unable to initialize Adapters");
assert(0);
} else {
@@ -693,4 +694,3 @@ void qd_python_unlock(void)
{
sys_mutex_unlock(ilock);
}
-
Modified: qpid/dispatch/trunk/src/router_pynode.c
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_pynode.c?rev=1602161&r1=1602160&r2=1602161&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_pynode.c (original)
+++ qpid/dispatch/trunk/src/router_pynode.c Thu Jun 12 13:46:43 2014
@@ -291,7 +291,7 @@ static PyObject* qd_set_valid_origins(Py
PyErr_SetString(PyExc_Exception, "Origin bit mask out of range");
return 0;
}
-
+
if (router->routers_by_mask_bit[maskbit] == 0) {
PyErr_SetString(PyExc_Exception, "Origin router Not Found");
return 0;
@@ -370,7 +370,7 @@ static PyObject* qd_map_destination(PyOb
PyErr_SetString(PyExc_Exception, "Router bit mask out of range");
return 0;
}
-
+
if (router->routers_by_mask_bit[maskbit] == 0) {
PyErr_SetString(PyExc_Exception, "Router Not Found");
return 0;
@@ -424,7 +424,7 @@ static PyObject* qd_unmap_destination(Py
PyErr_SetString(PyExc_Exception, "Router bit mask out of range");
return 0;
}
-
+
if (router->routers_by_mask_bit[maskbit] == 0) {
PyErr_SetString(PyExc_Exception, "Router Not Found");
return 0;
@@ -443,7 +443,7 @@ static PyObject* qd_unmap_destination(Py
sys_mutex_unlock(router->lock);
return 0;
}
-
+
qd_router_del_node_ref_LH(&addr->rnodes, rnode);
//
@@ -543,7 +543,7 @@ void qd_router_python_setup(qd_router_t
RouterAdapterType.tp_new = PyType_GenericNew;
if (PyType_Ready(&RouterAdapterType) < 0) {
- PyErr_Print();
+ qd_error_py();
qd_log(log_source, QD_LOG_CRITICAL, "Unable to initialize the Python
Router Adapter");
return;
}
@@ -611,7 +611,7 @@ void qd_router_python_setup(qd_router_t
Py_DECREF(adapterType);
if (!pyRouter) {
- PyErr_Print();
+ qd_error_py();
qd_log(log_source, QD_LOG_CRITICAL, "'RouterEngine' class cannot be
instantiated");
return;
}
@@ -651,13 +651,9 @@ void qd_pyrouter_tick(qd_router_t *route
qd_python_lock();
pArgs = PyTuple_New(0);
pValue = PyObject_CallObject(pyTick, pArgs);
- if (PyErr_Occurred()) {
- PyErr_Print();
- }
+ qd_error_py();
Py_DECREF(pArgs);
- if (pValue) {
- Py_DECREF(pValue);
- }
+ Py_XDECREF(pValue);
qd_python_unlock();
}
}
@@ -676,13 +672,9 @@ void qd_router_mobile_added(qd_router_t
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, PyString_FromString(address));
pValue = PyObject_CallObject(pyAdded, pArgs);
- if (PyErr_Occurred()) {
- PyErr_Print();
- }
+ qd_error_py();
Py_DECREF(pArgs);
- if (pValue) {
- Py_DECREF(pValue);
- }
+ Py_XDECREF(pValue);
qd_python_unlock();
free(address);
@@ -700,13 +692,9 @@ void qd_router_mobile_removed(qd_router_
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, PyString_FromString(address));
pValue = PyObject_CallObject(pyRemoved, pArgs);
- if (PyErr_Occurred()) {
- PyErr_Print();
- }
+ qd_error_py();
Py_DECREF(pArgs);
- if (pValue) {
- Py_DECREF(pValue);
- }
+ Py_XDECREF(pValue);
qd_python_unlock();
}
}
@@ -722,14 +710,9 @@ void qd_router_link_lost(qd_router_t *ro
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, PyInt_FromLong((long) link_mask_bit));
pValue = PyObject_CallObject(pyLinkLost, pArgs);
- if (PyErr_Occurred()) {
- PyErr_Print();
- }
+ qd_error_py();
Py_DECREF(pArgs);
- if (pValue) {
- Py_DECREF(pValue);
- }
+ Py_XDECREF(pValue);
qd_python_unlock();
}
}
-
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]