Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mod_python3] PyEval_AcquireThread freeze #2732

Open
21stcaveman opened this issue Jan 15, 2025 · 1 comment
Open

[mod_python3] PyEval_AcquireThread freeze #2732

21stcaveman opened this issue Jan 15, 2025 · 1 comment

Comments

@21stcaveman
Copy link

21stcaveman commented Jan 15, 2025

Trying to use mod_python3 on Rocky Linux 8.10, Python 3.6.8, freeswitch 1.10.10, compiled from source.

When I call "python test" in fs_cli (test.py is placed in /usr/share/freeswitch/scripts), the cli just freezes. Same thing happens if I use the python application in a dialplan.
"getenv PYTHONPATH" returns "/usr/share/freeswitch/scripts" to confirm the script location is correct.
This does not crash freeswitch, it just sits there and does nothing, like it is waiting to get GIL (deadlock)

Doing some debugging, it seems like it freezes on the PyEval_AcquireThread call in line eval_some_python function, line 244 of mod_python3.c

Any pointers on why this might be happening and how to fix it would be appreciated.

@21stcaveman
Copy link
Author

As an update, it works fine if I apply the following patch, and use PyGILState_Ensure instead:

diff --git a/src/mod/languages/mod_python3/mod_python3.c b/src/mod/languages/mod_python3/mod_python3.c
index 263c2de1d4..b5b07adf26 100644
--- a/src/mod/languages/mod_python3/mod_python3.c
+++ b/src/mod/languages/mod_python3/mod_python3.c
@@ -191,7 +191,7 @@ static void print_python_error(const char * script)
 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)
 {
-       PyThreadState *tstate = NULL;
+       PyGILState_STATE gstate;
        char *dupargs = NULL;
        char *argv[2] = { 0 };
        char *script = NULL;
@@ -230,18 +230,8 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Invoking py module: %s\n", script);
 
-       tstate = PyThreadState_New(mainThreadState->interp);
-       if (!tstate) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error acquiring tstate\n");
-               goto done;
-       }
-
-       /* Save state in thread struct so we can terminate it later if needed */
-       if (pt)
-               pt->tstate = tstate;
-
-       // swap in thread state
-       PyEval_AcquireThread(tstate);
+       // Ensure the GIL is acquired
+       gstate = PyGILState_Ensure();
 
        if (session) {
                switch_channel_t *channel = switch_core_session_get_channel(session);
@@ -350,12 +340,8 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi
        Py_XDECREF(eve);
        Py_XDECREF(sp);
 
-       if (tstate) {
-               // thread state must be cleared explicitly or we'll get memory leaks
-               PyThreadState_Clear(tstate);
-               PyEval_ReleaseThread(tstate);
-               PyThreadState_Delete(tstate);
-       }
+       // Release the GIL
+       PyGILState_Release(gstate);
 
   done:

But since I am not fully familiar with this module, I'm not sure if that is the right thing to do. Need some expert validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant