kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit f6c54042c50c48e939a698ef2146f11d29c2179a
parent f7a76f7e9618516fc054f18e3e8011fa06356ae9
Author: Joris Vink <joris@coders.se>
Date:   Thu, 14 Jul 2022 10:56:27 +0200

Improve Python 3.10.x support.

Python 3.10.x its PyIter_Send() will return PYGEN_ERROR if the
generator returned (as opposed to yielding) if the result returned
is Py_None and no argument was given to PyIter_Send(). Which is counter
intuitive since it seems it should give us a PYGEN_RETURN as per its
documentation.

It also no longer sets PyExc_StopIteration in this case so we cannot depend
on that anymore to figure out if a coroutine has finished.

This caused Kore to respond with a 500 immediately after coroutines
ran to completion as it was looking for the PyExc_StopIteration exception.

Fix this by simply doing another check if an exception happened before
we enter the code path where Kore would spew the 500.

Diffstat:
src/python.c | 10+++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/python.c b/src/python.c @@ -1090,7 +1090,12 @@ python_coro_run(struct python_coro *coro) #if PY_VERSION_HEX < 0x030a00a1 item = _PyGen_Send((PyGenObject *)coro->obj, NULL); #else - /* Depend on the result in item only. */ + /* + * Python 3.10.x its PyIter_Send() will return a PYGEN_ERROR + * if the coro returned (instead of yielding) and the result + * ends up being Py_None. This means the returned item is + * NULL but no StopIteration exception has occurred. + */ (void)PyIter_Send(coro->obj, NULL, &item); #endif @@ -1100,9 +1105,8 @@ python_coro_run(struct python_coro *coro) PyErr_Fetch(&type, &coro->result, &traceback); Py_DECREF(type); Py_XDECREF(traceback); - } else { + } else if (PyErr_Occurred()) { kore_python_log_error("coroutine"); - if (coro->request != NULL) { http_response(coro->request, HTTP_STATUS_INTERNAL_ERROR,