Patch-Source: https://github.com/FreeRADIUS/freeradius-server/pull/5208 --- From d6dcbbf38045a851007606ebdf11fb5ae5ddd0ff Mon Sep 17 00:00:00 2001 From: Antonio Torres Date: Tue, 24 Oct 2023 13:31:33 +0200 Subject: [PATCH] Fix build errors with Python 3.13 According to [1], the `PyEval_InitThreads()` (deprecated 3.9), `PyEval_AcquireLock()` and `PyEval_ReleaseLock()` (deprecated 3.2). functions, are removed in Python 3.13. `Py_SetProgramName()` is deprecated since 3.11 as well. `PyEval_InitThreads` can be deleted if running Python >= 3.10 as it simply does nothing from Python 3.9 [2]. Lock functions are replaced with `PyEval_RestoreThread` and `PyEval_SaveThread` as advised by Python docs [3], [4]. As for `Py_SetProgramName`, it should be replaced with PyConfig. The config is isolated to replicate behavior of `InitializeEx` [5]. [1]: https://docs.python.org/3.13/whatsnew/3.13.html [2]: https://docs.python.org/3/c-api/init.html#c.PyEval_InitThreads [3]: https://docs.python.org/3/c-api/init.html#c.PyEval_AcquireLock [4]: https://docs.python.org/3/c-api/init.html#c.PyEval_ReleaseLock [5]: https://docs.python.org/3/c-api/init_config.html#isolated-configuration --- src/modules/rlm_python3/rlm_python3.c | 31 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/modules/rlm_python3/rlm_python3.c b/src/modules/rlm_python3/rlm_python3.c index a200a988aeea9..c548a1201bcd2 100644 --- a/src/modules/rlm_python3/rlm_python3.c +++ b/src/modules/rlm_python3/rlm_python3.c @@ -679,12 +679,10 @@ static rlm_rcode_t do_python_single(REQUEST *request, PyObject *pFunc, char cons static void python_interpreter_free(PyThreadState *interp) { -DIAG_OFF(deprecated-declarations) - PyEval_AcquireLock(); + PyEval_RestoreThread(interp); PyThreadState_Swap(interp); Py_EndInterpreter(interp); - PyEval_ReleaseLock(); -DIAG_ON(deprecated-declarations) + PyEval_SaveThread(); } /** Destroy a thread state @@ -1117,7 +1115,21 @@ static int python_interpreter_init(rlm_python_t *inst, CONF_SECTION *conf) python_dlhandle = dlopen_libpython(RTLD_NOW | RTLD_GLOBAL); if (!python_dlhandle) WARN("Failed loading libpython symbols into global symbol table"); -#if PY_VERSION_HEX >= 0x03050000 +#if PY_VERSION_HEX > 0x030a0000 + PyStatus status; + + PyConfig config; + PyConfig_InitIsolatedConfig(&config); /* Isolated config: Don't override signal handlers - noop on subs calls */ + + wchar_t *name; + MEM(name = Py_DecodeLocale(main_config.name, NULL)); /* The value of argv[0] as a wide char string */ + status = PyConfig_SetString(&config, &config.program_name, name); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + return -1; + } + PyMem_RawFree(name); +#elif PY_VERSION_HEX >= 0x03050000 { wchar_t *name; @@ -1134,8 +1146,17 @@ static int python_interpreter_init(rlm_python_t *inst, CONF_SECTION *conf) } #endif +#if PY_VERSION_HEX > 0x030a0000 + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + return -1; + } + PyConfig_Clear(&config); +#else Py_InitializeEx(0); /* Don't override signal handlers - noop on subs calls */ PyEval_InitThreads(); /* This also grabs a lock (which we then need to release) */ +#endif main_interpreter = PyThreadState_Get(); /* Store reference to the main interpreter */ locked = true; }