From 6d53248011f036efa0a477fc94d061b7d25427cd Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 1 Aug 2014 17:46:05 +0200 Subject: [PATCH] Fix some Python reference count + Handle thread concurrency in Python code called from C. --- .../python/apixml2python/handwritten.mustache | 25 ++++++++++++++++--- tools/python/apixml2python/linphone.py | 9 ++++--- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/tools/python/apixml2python/handwritten.mustache b/tools/python/apixml2python/handwritten.mustache index 4717e6081..69f73533b 100644 --- a/tools/python/apixml2python/handwritten.mustache +++ b/tools/python/apixml2python/handwritten.mustache @@ -1,6 +1,10 @@ static void pylinphone_log(const char *level, int indent, const char *fmt, va_list args) { static int current_indent = 1; - PyObject *linphone_module = PyImport_ImportModule("linphone"); + PyObject *linphone_module; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + linphone_module = PyImport_ImportModule("linphone"); if ((linphone_module != NULL) && PyObject_HasAttrString(linphone_module, "__log_handler")) { PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler"); if ((log_handler != NULL) && PyFunction_Check(log_handler)) { @@ -17,8 +21,11 @@ static void pylinphone_log(const char *level, int indent, const char *fmt, va_li if (vsnprintf(logstr + i, sizeof(logstr) - i, fmt, args) > 0) { PyEval_CallFunction(log_handler, "ss", level, logstr); } + Py_DECREF(log_handler); } + Py_DECREF(linphone_module); } + PyGILState_Release(gstate); } static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...) { @@ -47,17 +54,27 @@ static const char * pylinphone_ortp_log_level_to_string(OrtpLogLevel lev) { } static void pylinphone_module_log_handler(OrtpLogLevel lev, const char *fmt, va_list args) { - PyObject *linphone_module = PyImport_ImportModule("linphone"); - const char *level = pylinphone_ortp_log_level_to_string(lev); + PyGILState_STATE gstate; + PyObject *linphone_module; + const char *level; + + gstate = PyGILState_Ensure(); + linphone_module = PyImport_ImportModule("linphone"); + level = pylinphone_ortp_log_level_to_string(lev); if ((linphone_module != NULL) && PyObject_HasAttrString(linphone_module, "__log_handler")) { PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler"); if ((log_handler != NULL) && PyFunction_Check(log_handler)) { char logstr[4096]; if (vsnprintf(logstr, sizeof(logstr), fmt, args) > 0) { - PyEval_CallFunction(log_handler, "ss", level, logstr); + if (PyEval_CallFunction(log_handler, "ss", level, logstr) == NULL) { + PyErr_Print(); + } } + Py_DECREF(log_handler); } + Py_DECREF(linphone_module); } + PyGILState_Release(gstate); } static void pylinphone_init_logging(void) { diff --git a/tools/python/apixml2python/linphone.py b/tools/python/apixml2python/linphone.py index e0a0a050c..42e6c5786 100644 --- a/tools/python/apixml2python/linphone.py +++ b/tools/python/apixml2python/linphone.py @@ -556,7 +556,8 @@ class EventCallbackMethodDefinition(MethodDefinition): def format_local_variables_definition(self): common = \ """ pylinphone_CoreObject *pylc = (pylinphone_CoreObject *)linphone_core_get_user_data(lc); - PyObject *func = PyDict_GetItemString(pylc->vtable_dict, "{name}");""".format(name=self.class_['event_name']) + PyObject *func = PyDict_GetItemString(pylc->vtable_dict, "{name}"); + PyGILState_STATE pygil_state;""".format(name=self.class_['event_name']) specific = '' for xml_method_arg in self.xml_method_args: arg_name = 'py' + xml_method_arg.get('name') @@ -568,7 +569,7 @@ class EventCallbackMethodDefinition(MethodDefinition): return "{common}\n{specific}".format(common=common, specific=specific) def format_arguments_parsing(self): - body = '' + body = "\tpygil_state = PyGILState_Ensure();\n" for xml_method_arg in self.xml_method_args: arg_name = xml_method_arg.get('name') arg_type = xml_method_arg.get('type') @@ -629,10 +630,10 @@ class EventCallbackMethodDefinition(MethodDefinition): """.format(fmt=fmt, args=args) def format_return_trace(self): - return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s\", __FUNCTION__);" + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s\", __FUNCTION__);\n" def format_return_result(self): - return '' + return '\tPyGILState_Release(pygil_state);' def format(self): body = MethodDefinition.format(self)