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.
This commit is contained in:
Joris Vink 2022-07-14 10:56:27 +02:00
parent f7a76f7e96
commit f6c54042c5
1 changed files with 7 additions and 3 deletions

View File

@ -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,