@@ -253,7 +253,15 @@ static PyObject* py_request_stop(PyObject *self) {
253253static PyObject * py_main (PyObject * self , PyObject * args ) {
254254 DEBUG_PRINT ("Initializing main." );
255255 const char * argv [] = {TOSTRING (MODULE_NAME ), NULL };
256+
257+ // Initialize the Python interpreter
258+ Py_Initialize ();
259+
260+ DEBUG_PRINT ("Initialized the Python interpreter." );
261+
262+ Py_BEGIN_ALLOW_THREADS
256263 lf_reactor_c_main (1 , argv );
264+ Py_END_ALLOW_THREADS
257265
258266 Py_INCREF (Py_None );
259267 return Py_None ;
@@ -965,25 +973,22 @@ PyObject* convert_C_action_to_py(void* action) {
965973 */
966974PyObject *
967975get_python_function (string module , string class , int instance_id , string func ) {
968-
969- // Set if the interpreter is already initialized
970- int is_initialized = 0 ;
971-
972- if (Py_IsInitialized ()) {
973- is_initialized = 1 ;
974- }
975-
976976 DEBUG_PRINT ("Starting the function start()." );
977977
978978 // Necessary PyObject variables to load the react() function from test.py
979979 PyObject * pFileName , * pModule , * pDict , * pClasses , * pClass , * pFunc ;
980980
981981 PyObject * rValue ;
982982
983- // Initialize the Python interpreter
984- Py_Initialize ();
985-
986- DEBUG_PRINT ("Initialized the Python interpreter." );
983+ // According to
984+ // https://docs.python.org/3/c-api/init.html#non-python-created-threads
985+ // the following code does the following:
986+ // - Register this thread with the interpreter
987+ // - Acquire the GIL (Global Interpreter Lock)
988+ // - Store (return) the thread pointer
989+ // When done, we should always call PyGILState_Release(gstate);
990+ PyGILState_STATE gstate ;
991+ gstate = PyGILState_Ensure ();
987992
988993 // If the Python module is already loaded, skip this.
989994 if (globalPythonModule == NULL ) {
@@ -992,8 +997,7 @@ get_python_function(string module, string class, int instance_id, string func) {
992997
993998 // Set the Python search path to be the current working directory
994999 char cwd [PATH_MAX ];
995- if ( getcwd (cwd , sizeof (cwd )) == NULL )
996- {
1000+ if ( getcwd (cwd , sizeof (cwd )) == NULL ) {
9971001 error_print_and_exit ("Failed to get the current working directory." );
9981002 }
9991003
@@ -1019,6 +1023,8 @@ get_python_function(string module, string class, int instance_id, string func) {
10191023 if (pDict == NULL ) {
10201024 PyErr_Print ();
10211025 error_print ("Failed to load contents of module %s." , module );
1026+ /* Release the thread. No Python API allowed beyond this point. */
1027+ PyGILState_Release (gstate );
10221028 return 1 ;
10231029 }
10241030
@@ -1041,6 +1047,8 @@ get_python_function(string module, string class, int instance_id, string func) {
10411047 if (pClasses == NULL ){
10421048 PyErr_Print ();
10431049 error_print ("Failed to load class list \"%s\" in module %s." , class , module );
1050+ /* Release the thread. No Python API allowed beyond this point. */
1051+ PyGILState_Release (gstate );
10441052 return 1 ;
10451053 }
10461054
@@ -1050,6 +1058,8 @@ get_python_function(string module, string class, int instance_id, string func) {
10501058 if (pClass == NULL ) {
10511059 PyErr_Print ();
10521060 error_print ("Failed to load class \"%s[%d]\" in module %s." , class , instance_id , module );
1061+ /* Release the thread. No Python API allowed beyond this point. */
1062+ PyGILState_Release (gstate );
10531063 return 1 ;
10541064 }
10551065
@@ -1065,6 +1075,8 @@ get_python_function(string module, string class, int instance_id, string func) {
10651075 if (pFunc && PyCallable_Check (pFunc )) {
10661076 DEBUG_PRINT ("Calling function %s from class %s[%d]." , func , class , instance_id );
10671077 Py_INCREF (pFunc );
1078+ /* Release the thread. No Python API allowed beyond this point. */
1079+ PyGILState_Release (gstate );
10681080 return pFunc ;
10691081 }
10701082 else {
@@ -1085,11 +1097,8 @@ get_python_function(string module, string class, int instance_id, string func) {
10851097
10861098 DEBUG_PRINT ("Done with start()." );
10871099
1088- if (is_initialized == 0 ) {
1089- /* We are the first to initilize the Pyton interpreter. Destroy it when done. */
1090- Py_FinalizeEx ();
1091- }
1092-
10931100 Py_INCREF (Py_None );
1101+ /* Release the thread. No Python API allowed beyond this point. */
1102+ PyGILState_Release (gstate );
10941103 return Py_None ;
10951104}
0 commit comments