From 6c937ba1e7314d595bdeb3414995c5161a138435 Mon Sep 17 00:00:00 2001 From: Ralf Ertzinger Date: Wed, 19 Jul 2023 19:42:31 +0200 Subject: [PATCH] This adds support for Python 3.12 The code compiles, and runs all my (admittedly pretty primitive) web applications. There may still be hidden issues in more complicated scenarios (like threading support). --- plugins/python/python_plugin.c | 47 ++++++++++++++++++++++++++++++---- plugins/python/uwsgi_python.h | 14 +++++++++- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index dcb5d348e..1cd5f895a 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -233,6 +233,9 @@ void uwsgi_python_pthread_child(void) { PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""} }; PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARGS, ""} }; +#ifdef PYTHREE +PyObject *init_uwsgi3(void); +#endif int uwsgi_python_init() { char *pyversion = strchr(Py_GetVersion(), '\n'); @@ -298,6 +301,9 @@ int uwsgi_python_init() { wchar_t *pname = uwsgi_calloc(sizeof(wchar_t) * (strlen(program_name)+1)); mbstowcs(pname, program_name, strlen(program_name)+1); Py_SetProgramName(pname); +#ifdef UWSGI_PY312 + PyImport_AppendInittab("uwsgi", init_uwsgi3); +#endif #else Py_SetProgramName(program_name); #endif @@ -695,7 +701,9 @@ void init_uwsgi_embedded_module() { #ifdef PYTHREE +#ifndef UWSGI_PY312 PyImport_AppendInittab("uwsgi", init_uwsgi3); +#endif new_uwsgi_module = PyImport_AddModule("uwsgi"); #else new_uwsgi_module = Py_InitModule3("uwsgi", NULL, uwsgi_py_doc); @@ -1208,7 +1216,10 @@ void uwsgi_python_init_apps() { // prepare for stack suspend/resume if (uwsgi.async > 0) { -#ifdef UWSGI_PY311 +#ifdef UWSGI_PY312 + up.current_c_recursion_remaining = uwsgi_malloc(sizeof(int)*uwsgi.async); + up.current_py_recursion_remaining = uwsgi_malloc(sizeof(int)*uwsgi.async); +#elif defined UWSGI_PY311 up.current_recursion_remaining = uwsgi_malloc(sizeof(int)*uwsgi.async); #else up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async); @@ -1360,7 +1371,12 @@ void uwsgi_python_pre_uwsgi_fork() { // Acquire the gil and import lock before forking in order to avoid // deadlocks in workers UWSGI_GET_GIL +#if defined UWSGI_PY312 + PyInterpreterState *interp = PyInterpreterState_Get(); + _PyImport_AcquireLock(interp); +#else _PyImport_AcquireLock(); +#endif } } @@ -1372,7 +1388,12 @@ void uwsgi_python_post_uwsgi_fork(int step) { if (uwsgi.has_threads) { if (step == 0) { // Release locks within master process +#if defined UWSGI_PY312 + PyInterpreterState *interp = PyInterpreterState_Get(); + _PyImport_ReleaseLock(interp); +#else _PyImport_ReleaseLock(); +#endif UWSGI_RELEASE_GIL } else { @@ -1643,7 +1664,11 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) { PyGILState_Release(pgst); if (wsgi_req) { -#ifdef UWSGI_PY311 +#ifdef UWSGI_PY312 + up.current_c_recursion_remaining[wsgi_req->async_id] = tstate->c_recursion_remaining; + up.current_py_recursion_remaining[wsgi_req->async_id] = tstate->py_recursion_remaining; + up.current_frame[wsgi_req->async_id] = tstate->cframe; +#elif defined UWSGI_PY311 up.current_recursion_remaining[wsgi_req->async_id] = tstate->recursion_remaining; up.current_frame[wsgi_req->async_id] = tstate->cframe; #else @@ -1652,7 +1677,11 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) { #endif } else { -#ifdef UWSGI_PY311 +#ifdef UWSGI_PY312 + up.current_main_c_recursion_remaining = tstate->c_recursion_remaining; + up.current_main_py_recursion_remaining = tstate->py_recursion_remaining; + up.current_main_frame = tstate->cframe; +#elif defined UWSGI_PY311 up.current_main_recursion_remaining = tstate->recursion_remaining; up.current_main_frame = tstate->cframe; #else @@ -1886,7 +1915,11 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) { PyGILState_Release(pgst); if (wsgi_req) { -#ifdef UWSGI_PY311 +#ifdef UWSGI_PY312 + tstate->c_recursion_remaining = up.current_c_recursion_remaining[wsgi_req->async_id]; + tstate->py_recursion_remaining = up.current_py_recursion_remaining[wsgi_req->async_id]; + tstate->cframe = up.current_frame[wsgi_req->async_id]; +#elif defined UWSGI_PY311 tstate->recursion_remaining = up.current_recursion_remaining[wsgi_req->async_id]; tstate->cframe = up.current_frame[wsgi_req->async_id]; #else @@ -1895,7 +1928,11 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) { #endif } else { -#ifdef UWSGI_PY311 +#ifdef UWSGI_PY312 + tstate->c_recursion_remaining = up.current_main_c_recursion_remaining; + tstate->py_recursion_remaining = up.current_main_py_recursion_remaining; + tstate->cframe = up.current_main_frame; +#elif defined UWSGI_PY311 tstate->recursion_remaining = up.current_main_recursion_remaining; tstate->cframe = up.current_main_frame; #else diff --git a/plugins/python/uwsgi_python.h b/plugins/python/uwsgi_python.h index 1e75fd641..961a46c49 100644 --- a/plugins/python/uwsgi_python.h +++ b/plugins/python/uwsgi_python.h @@ -21,6 +21,10 @@ # define UWSGI_PY311 #endif +#if (PY_VERSION_HEX >= 0x030c0000) +# define UWSGI_PY312 +#endif + #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7 #define HAS_NOT_PyMemoryView_FromBuffer #endif @@ -182,7 +186,15 @@ struct uwsgi_python { char *callable; -#ifdef UWSGI_PY311 +#ifdef UWSGI_PY312 + int *current_c_recursion_remaining; + int *current_py_recursion_remaining; + _PyCFrame **current_frame; + + int current_main_c_recursion_remaining; + int current_main_py_recursion_remaining; + _PyCFrame *current_main_frame; +#elif defined UWSGI_PY311 int *current_recursion_remaining; _PyCFrame **current_frame;