* Brian Fertig <brian.fertig@convergencetek.com>
* Johny Kadarisman <jkr888@gmail.com>
* Traun Leyden <tleyden@branchcut.com>
+ * Heimo Stieg <heimo.stieg@nextiraone.eu>
*
* mod_python.c -- Python Module
*
*/
#include <Python.h>
+#include <frameobject.h>
#ifndef _REENTRANT
#define _REENTRANT
#include <switch.h>
#include "mod_python_extra.h"
+#include <string.h>
PyThreadState *mainThreadState = NULL;
int py_thread(const char *text);
static void set_max_recursion_depth(void);
static switch_api_interface_t python_run_interface;
+static void print_python_error(const char * script);
SWITCH_MODULE_LOAD_FUNCTION(mod_python_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_python_shutdown);
struct switch_py_thread *thread_pool_head = NULL;
static switch_mutex_t *THREAD_POOL_LOCK = NULL;
+
+
+/**
+* This function is similiar to PyErr_Print. It uses the freeswitch print/log mechanism instead of the python sys.stderr
+*/
+static void print_python_error(const char * script)
+{
+ PyObject *pyType = NULL, *pyValue = NULL, *pyTraceback = NULL, *pyString = NULL;
+ PyObject *pyModule=NULL, *pyFunction = NULL, *pyResult = NULL;
+ char * buffer = (char*) malloc( 20 * 1024 * sizeof(char));
+ /* Variables for the traceback */
+ PyTracebackObject * pyTB = NULL/*, *pyTB2 = NULL*/;
+ char sTemp[256];
+
+ if (buffer == NULL ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not enough Memory to create the error buffer");
+ }
+
+ /* just for security that we will always have a string terminater */
+ memset(buffer, 0, 20 * 1024 * sizeof(char) );
+
+ /*Get the errordata*/
+ PyErr_Fetch(&pyType, &pyValue, &pyTraceback);
+ PyErr_NormalizeException(&pyType, &pyValue, &pyTraceback);
+
+
+ /* Printing header*/
+ sprintf(buffer, "Python Error by calling script \"%s\": ", script );
+
+ if (pyType != NULL && (pyString=PyObject_Str(pyType))!=NULL && (PyString_Check(pyString))) {
+ strcat(buffer, PyString_AsString(pyString));
+ } else {
+ strcat(buffer, "<unknown exception type> ");
+ }
+ Py_XDECREF(pyString);
+
+
+ /*Print error message*/
+ if (pyValue != NULL && (pyString=PyObject_Str(pyValue))!=NULL && (PyString_Check(pyString))) {
+ strcat(buffer, "\nMessage: ");
+ strcat(buffer, PyString_AsString(pyString));
+ } else {
+ strcat(buffer, "\nMessage: <unknown exception date> ");
+ }
+ Py_XDECREF(pyString);
+
+
+ /* Print the traceback */
+ if (pyTraceback != NULL && PyTraceBack_Check(pyTraceback)) {
+
+ /*loading traceback module to create the exception data*/
+ pyModule = PyImport_ImportModule("traceback");
+ if (pyModule) {
+ strcat(buffer, "\nException: ");
+ pyFunction = PyObject_GetAttrString(pyModule, "format_exc");
+ if (pyFunction) {
+ pyResult = PyObject_CallObject(pyFunction, NULL);
+ if (pyResult && PyString_Check(pyResult)) {
+ strcat(buffer, PyString_AsString(pyResult));
+ } else {
+ strcat(buffer, "<exception not available>");
+ }
+ Py_XDECREF(pyFunction);
+
+ }
+ Py_XDECREF(pyModule);
+
+ }
+
+ /* Print traceback header */
+ strcat(buffer, "\nTraceback (most recent call last)");
+ pyTB = (PyTracebackObject*) pyTraceback;
+
+ /* Traceback */
+ do {
+ sprintf((char*)sTemp, "\n\tFile: \"%s\", line %i, in %s",
+ PyString_AsString(pyTB->tb_frame->f_code->co_filename),
+ pyTB->tb_lineno,
+ PyString_AsString(pyTB->tb_frame->f_code->co_name) );
+ strcat(buffer, (char*)sTemp);
+
+ pyTB=pyTB->tb_next;
+ } while(pyTB != NULL);
+ }
+
+ PyErr_Restore(pyType,pyValue,pyTraceback);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", buffer);
+
+ /* free the resources, we dont need memory leaks here */
+ free(buffer);
+}
+
+
static void eval_some_python(const char *funcname, char *args, switch_core_session_t *session, switch_stream_handle_t *stream, switch_event_t *params,
char **str, struct switch_py_thread *pt)
{
module = PyImport_ImportModule((char *) script);
if (!module) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error importing module\n");
- PyErr_Print();
+ print_python_error(script);
PyErr_Clear();
goto done_swap_out;
}
module = PyImport_ReloadModule(module);
if (!module) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error reloading module\n");
- PyErr_Print();
+ print_python_error(script);
PyErr_Clear();
goto done_swap_out;
}
function = PyObject_GetAttrString(module, (char *) funcname);
if (!function) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module does not define %s\n", funcname);
- PyErr_Print();
+ print_python_error(script);
PyErr_Clear();
goto done_swap_out;
}
} else if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
// Print error, but ignore SystemExit
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python script\n");
- PyErr_Print();
+ print_python_error(script);
PyErr_Clear();
PyRun_SimpleString("python_makes_sense");
PyGC_Collect();
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set python recursion limit to %d\n", newMaxRecursionDepth);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set recursion limit to %d\n", newMaxRecursionDepth);
- PyErr_Print();
+ print_python_error("_freeswitch");
PyErr_Clear();
PyRun_SimpleString("python_makes_sense");
PyGC_Collect();