From 3a707a316ad9bed3708c43e1b36f9ec12716cd78 Mon Sep 17 00:00:00 2001
From: Michael Jerris <mike@jerris.com>
Date: Thu, 10 May 2007 18:51:47 +0000
Subject: [PATCH] merge fix for MODLANG-15 from Traun Leyden.  Thanks Traun.

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5130 d0543943-73ff-0310-b7d9-9358b9ac24b2
---
 .../mod_python/freeswitch_python.cpp          | 22 ++++++++-
 src/mod/languages/mod_python/mod_python.c     | 48 +++++++++----------
 2 files changed, 44 insertions(+), 26 deletions(-)

diff --git a/src/mod/languages/mod_python/freeswitch_python.cpp b/src/mod/languages/mod_python/freeswitch_python.cpp
index 2846d33a28..13c799fe1a 100644
--- a/src/mod/languages/mod_python/freeswitch_python.cpp
+++ b/src/mod/languages/mod_python/freeswitch_python.cpp
@@ -9,8 +9,8 @@ SessionContainer::SessionContainer(char *nuuid)
     tts_name = NULL;
     voice_name = NULL;
 
-	if (session = switch_core_session_locate(uuid)) {
-		channel = switch_core_session_get_channel(session);
+       if (session = switch_core_session_locate(uuid)) {
+	        channel = switch_core_session_get_channel(session);
     }
 }
 
@@ -83,7 +83,10 @@ int SessionContainer::play_file(char *file, char *timer_name)
 		ap = &args;
     }
 
+    Py_BEGIN_ALLOW_THREADS
 	status = switch_ivr_play_file(session, NULL, file, ap);
+    Py_END_ALLOW_THREADS
+
     return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
 }
 
@@ -114,7 +117,10 @@ int SessionContainer::speak_text(char *text)
 		ap = &args;
     }
 
+    Py_BEGIN_ALLOW_THREADS
 	status = switch_ivr_speak_text(session, tts_name, voice_name, codec->implementation->samples_per_second, text, ap);
+    Py_END_ALLOW_THREADS
+
     return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
 }
 
@@ -129,7 +135,11 @@ int SessionContainer::get_digits(char *dtmf_buf, int len, char *terminators, cha
 {
     switch_status_t status;
 	sanity_check(-1);
+
+    Py_BEGIN_ALLOW_THREADS
     status = switch_ivr_collect_digits_count(session, dtmf_buf,(uint32_t) len,(uint32_t) len, terminators, terminator, (uint32_t) timeout);
+    Py_END_ALLOW_THREADS
+
     return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
 }
 
@@ -137,7 +147,11 @@ int SessionContainer::transfer(char *extension, char *dialplan, char *context)
 {
     switch_status_t status;
 	sanity_check(-1);
+
+    Py_BEGIN_ALLOW_THREADS
     status = switch_ivr_session_transfer(session, extension, dialplan, context);
+    Py_END_ALLOW_THREADS
+
     return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
 }
 
@@ -146,9 +160,13 @@ int SessionContainer::play_and_get_digits(int min_digits, int max_digits, int ma
 {
     switch_status_t status;
 	sanity_check(-1);
+
+    Py_BEGIN_ALLOW_THREADS
     status = switch_play_and_get_digits( session, (uint32_t) min_digits,(uint32_t) max_digits,
             (uint32_t) max_tries, (uint32_t) timeout, 
             terminators, audio_files, bad_input_audio_files, dtmf_buf, 128, digits_regex);
+    Py_END_ALLOW_THREADS
+
     return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
 }
 
diff --git a/src/mod/languages/mod_python/mod_python.c b/src/mod/languages/mod_python/mod_python.c
index 811ac4cdff..f1c1742ee4 100644
--- a/src/mod/languages/mod_python/mod_python.c
+++ b/src/mod/languages/mod_python/mod_python.c
@@ -25,6 +25,7 @@
  * 
  * Brian Fertig <brian.fertig@convergencetek.com>
  * Johny Kadarisman <jkr888@gmail.com>
+ * Traun Leyden <tleyden@branchcut.com>
  *
  * mod_python.c -- Python Module
  *
@@ -43,6 +44,7 @@
 #include <switch.h>
 
 
+static PyThreadState *mainThreadState = NULL;
 
 void init_freeswitch(void);
 static switch_api_interface_t python_run_interface;
@@ -51,7 +53,7 @@ const char modname[] = "mod_python";
 
 static void eval_some_python(char *uuid, char *args)
 {
-	PyThreadState *tstate;
+	PyThreadState *tstate = NULL;
 	FILE *pythonfile = NULL;
 	char *dupargs = NULL;
 	char *argv[128] = {0};
@@ -97,16 +99,15 @@ static void eval_some_python(char *uuid, char *args)
 
 
 	if ((pythonfile = fopen(script_path, "r"))) {
-		tstate = Py_NewInterpreter();
 
+		PyEval_AcquireLock();
+		tstate = PyThreadState_New(mainThreadState->interp);
 		if (!tstate) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error acquiring tstate\n");
 			goto done;
 		}
-		
-
-		PyThreadState_Clear(tstate);
-		init_freeswitch();
+		PyThreadState_Swap(tstate);
+		init_freeswitch(); 
 		PyRun_SimpleString("from freeswitch import *");
 		if (uuid) {
 			char code[128];
@@ -115,7 +116,11 @@ static void eval_some_python(char *uuid, char *args)
 		}
 		PySys_SetArgv(argc - lead, &argv[lead]);
 		PyRun_SimpleFile(pythonfile, script);
-		Py_EndInterpreter(tstate);
+		PyThreadState_Swap(NULL);
+		PyThreadState_Clear(tstate);
+		PyThreadState_Delete(tstate);
+		PyEval_ReleaseLock();
+
 		
 	} else {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error running %s\n", script_path);
@@ -134,7 +139,6 @@ static void eval_some_python(char *uuid, char *args)
 
 static void python_function(switch_core_session_t *session, char *data)
 {
-
 	eval_some_python(switch_core_session_get_uuid(session), (char *)data);
 	
 }
@@ -217,9 +221,6 @@ static switch_loadable_module_interface_t python_module_interface = {
 	/*.directory_interface */ NULL
 };
 
-//static PyThreadState *gtstate;
-static PyThreadState *mainThreadState;
-
 SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
 {
 	/* connect my internal structure to the blank pointer passed to me */
@@ -231,10 +232,9 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod
 
 	mainThreadState = PyThreadState_Get();
 
-	PyEval_ReleaseLock();	
+	PyThreadState_Swap(NULL); 
 
-	eval_some_python(NULL, "init_python.py");
-	PyThreadState_Swap(NULL);
+	PyEval_ReleaseLock();	
 
 	/* indicate that the module should continue to be loaded */
 	return SWITCH_STATUS_SUCCESS;
@@ -244,19 +244,19 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod
   Called when the system shuts down*/
 SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void)
 {
+    PyInterpreterState *mainInterpreterState;
+    PyThreadState *myThreadState;
 
-	PyInterpreterState *mainInterpreterState;
-	PyThreadState *myThreadState;
+    PyEval_AcquireLock();
+    mainInterpreterState = mainThreadState->interp;
+    myThreadState = PyThreadState_New(mainInterpreterState);
+    PyThreadState_Swap(myThreadState);
+    PyEval_ReleaseLock();
 
-	PyEval_AcquireLock();
-	mainInterpreterState = mainThreadState->interp;
-	myThreadState = PyThreadState_New(mainInterpreterState);
-	PyThreadState_Swap(myThreadState);
-	PyEval_ReleaseLock();
+    Py_Finalize();
+    PyEval_ReleaseLock();
+    return SWITCH_STATUS_SUCCESS;
 
-	Py_Finalize();
-	PyEval_ReleaseLock();
-	return SWITCH_STATUS_SUCCESS;
 }