From bb461ce50d997604a33269882f73a9fa26eb49c6 Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Thu, 15 Dec 2011 17:23:48 -0500 Subject: [PATCH] FS-3615 --resolve Please Test ! --- src/mod/languages/mod_python/mod_python.c | 108 +++++++++++++++++++++- 1 file changed, 103 insertions(+), 5 deletions(-) diff --git a/src/mod/languages/mod_python/mod_python.c b/src/mod/languages/mod_python/mod_python.c index 1245dea867..b92526e135 100644 --- a/src/mod/languages/mod_python/mod_python.c +++ b/src/mod/languages/mod_python/mod_python.c @@ -26,12 +26,14 @@ * Brian Fertig * Johny Kadarisman * Traun Leyden + * Heimo Stieg * * mod_python.c -- Python Module * */ #include +#include #ifndef _REENTRANT #define _REENTRANT @@ -43,6 +45,7 @@ #include #include "mod_python_extra.h" +#include PyThreadState *mainThreadState = NULL; @@ -50,6 +53,7 @@ void init_freeswitch(void); 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); @@ -70,6 +74,100 @@ struct switch_py_thread { 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, " "); + } + 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: "); + } + 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, ""); + } + 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) { @@ -131,7 +229,7 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi 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; } @@ -139,7 +237,7 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi 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; } @@ -147,7 +245,7 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi 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; } @@ -193,7 +291,7 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi } 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(); @@ -310,7 +408,7 @@ static void set_max_recursion_depth(void) 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();