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

Add Python 3.11 support #2453

Merged
merged 1 commit into from
Jul 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions plugins/python/profiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
}
#endif

#if PY_VERSION_HEX < 0x030900B1
PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using https://github.com/python/pythoncapi-compat/ here would be interesting here, but I tried to mimick the coding style of the existing uwsgi code.

I can add PyFrame_GetLineNumber() to pythoncapi-compat if you want. Maybe using pythoncapi_compat.h can be done later.

{
Py_INCREF(frame->f_code);
return frame->f_code;
}
#endif

#ifdef PYTHREE
#undef PyString_AsString
static char *PyString_AsString(PyObject *o) {
Expand All @@ -27,27 +35,32 @@ int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, Py
static uint64_t last_ts = 0;
uint64_t now = uwsgi_micros();
uint64_t delta = 0;
PyCodeObject *code;

switch(what) {
case PyTrace_CALL:
if (last_ts == 0) delta = 0;
else delta = now - last_ts;
last_ts = now;
code = PyFrame_GetCode(frame);
uwsgi_log("[uWSGI Python profiler %llu] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
(unsigned long long) delta,
PyString_AsString(frame->f_code->co_filename),
PyString_AsString(code->co_filename),
PyFrame_GetLineNumber(frame),
PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount, frame->f_code->co_stacksize);
PyString_AsString(code->co_name), code->co_argcount, code->co_stacksize);
Py_DECREF(code);
break;
case PyTrace_C_CALL:
if (last_ts == 0) delta = 0;
else delta = now - last_ts;
last_ts = now;
code = PyFrame_GetCode(frame);
uwsgi_log("[uWSGI Python profiler %llu] C CALL: %s (line %d) -> %s %d args, stacksize %d\n",
(unsigned long long) delta,
PyString_AsString(frame->f_code->co_filename),
PyString_AsString(code->co_filename),
PyFrame_GetLineNumber(frame),
PyEval_GetFuncName(arg), frame->f_code->co_argcount, frame->f_code->co_stacksize);
PyEval_GetFuncName(arg), code->co_argcount, code->co_stacksize);
Py_DECREF(code);
break;
}

Expand All @@ -68,7 +81,9 @@ int uwsgi_python_tracer(PyObject *obj, PyFrameObject *frame, int what, PyObject
delta = now - last_ts;
}
last_ts = now;
uwsgi_log("[uWSGI Python profiler %llu] file %s line %d: %s argc:%d\n", (unsigned long long)delta, PyString_AsString(frame->f_code->co_filename), PyFrame_GetLineNumber(frame), PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount);
PyCodeObject *code = PyFrame_GetCode(frame);
uwsgi_log("[uWSGI Python profiler %llu] file %s line %d: %s argc:%d\n", (unsigned long long)delta, PyString_AsString(code->co_filename), PyFrame_GetLineNumber(frame), PyString_AsString(code->co_name), code->co_argcount);
Py_DECREF(code);
}

return 0;
Expand Down
26 changes: 25 additions & 1 deletion plugins/python/python_plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -1185,8 +1185,12 @@ void uwsgi_python_init_apps() {

// prepare for stack suspend/resume
if (uwsgi.async > 0) {
#ifdef UWSGI_PY311
up.current_recursion_remaining = uwsgi_malloc(sizeof(int)*uwsgi.async);
#else
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
#endif
up.current_frame = uwsgi_malloc(sizeof(up.current_frame[0])*uwsgi.async);
}

struct uwsgi_string_list *upli = up.import_list;
Expand Down Expand Up @@ -1581,12 +1585,22 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
PyGILState_Release(pgst);

if (wsgi_req) {
#ifdef UWSGI_PY311
up.current_recursion_remaining[wsgi_req->async_id] = tstate->recursion_remaining;
up.current_frame[wsgi_req->async_id] = tstate->cframe;
#else
up.current_recursion_depth[wsgi_req->async_id] = tstate->recursion_depth;
up.current_frame[wsgi_req->async_id] = tstate->frame;
#endif
}
else {
#ifdef UWSGI_PY311
up.current_main_recursion_remaining = tstate->recursion_remaining;
up.current_main_frame = tstate->cframe;
#else
up.current_main_recursion_depth = tstate->recursion_depth;
up.current_main_frame = tstate->frame;
#endif
}

}
Expand Down Expand Up @@ -1814,12 +1828,22 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
PyGILState_Release(pgst);

if (wsgi_req) {
xrmx marked this conversation as resolved.
Show resolved Hide resolved
#ifdef UWSGI_PY311
tstate->recursion_remaining = up.current_recursion_remaining[wsgi_req->async_id];
tstate->cframe = up.current_frame[wsgi_req->async_id];
#else
tstate->recursion_depth = up.current_recursion_depth[wsgi_req->async_id];
tstate->frame = up.current_frame[wsgi_req->async_id];
#endif
}
else {
#ifdef UWSGI_PY311
tstate->recursion_remaining = up.current_main_recursion_remaining;
tstate->cframe = up.current_main_frame;
#else
tstate->recursion_depth = up.current_main_recursion_depth;
tstate->frame = up.current_main_frame;
#endif
}

}
Expand Down
12 changes: 12 additions & 0 deletions plugins/python/uwsgi_python.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#define UWSGI_PYTHON_OLD
#endif

#if (PY_VERSION_HEX >= 0x030b0000)
# define UWSGI_PY311
#endif

#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7
#define HAS_NOT_PyMemoryView_FromBuffer
#endif
Expand Down Expand Up @@ -177,11 +181,19 @@ struct uwsgi_python {

char *callable;

#ifdef UWSGI_PY311
int *current_recursion_remaining;
_PyCFrame **current_frame;

int current_main_recursion_remaining;
_PyCFrame *current_main_frame;
#else
int *current_recursion_depth;
struct _frame **current_frame;

int current_main_recursion_depth;
struct _frame *current_main_frame;
#endif

void (*swap_ts)(struct wsgi_request *, struct uwsgi_app *);
void (*reset_ts)(struct wsgi_request *, struct uwsgi_app *);
Expand Down