mirror of
https://github.com/python/cpython.git
synced 2025-12-15 21:44:50 +00:00
gh-112182: Replace StopIteration with RuntimeError for future (#113220)
When an `StopIteration` raises into `asyncio.Future`, this will cause a thread to hang. This commit address this by not raising an exception and silently transforming the `StopIteration` with a `RuntimeError`, which the caller can reconstruct from `fut.exception().__cause__`
This commit is contained in:
parent
5d8a3e74b5
commit
4826d52338
4 changed files with 49 additions and 12 deletions
|
|
@ -597,12 +597,27 @@ future_set_exception(asyncio_state *state, FutureObj *fut, PyObject *exc)
|
|||
PyErr_SetString(PyExc_TypeError, "invalid exception object");
|
||||
return NULL;
|
||||
}
|
||||
if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) {
|
||||
if (PyErr_GivenExceptionMatches(exc_val, PyExc_StopIteration)) {
|
||||
const char *msg = "StopIteration interacts badly with "
|
||||
"generators and cannot be raised into a "
|
||||
"Future";
|
||||
PyObject *message = PyUnicode_FromString(msg);
|
||||
if (message == NULL) {
|
||||
Py_DECREF(exc_val);
|
||||
return NULL;
|
||||
}
|
||||
PyObject *err = PyObject_CallOneArg(PyExc_RuntimeError, message);
|
||||
Py_DECREF(message);
|
||||
if (err == NULL) {
|
||||
Py_DECREF(exc_val);
|
||||
return NULL;
|
||||
}
|
||||
assert(PyExceptionInstance_Check(err));
|
||||
|
||||
PyException_SetCause(err, Py_NewRef(exc_val));
|
||||
PyException_SetContext(err, Py_NewRef(exc_val));
|
||||
Py_DECREF(exc_val);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"StopIteration interacts badly with generators "
|
||||
"and cannot be raised into a Future");
|
||||
return NULL;
|
||||
exc_val = err;
|
||||
}
|
||||
|
||||
assert(!fut->fut_exception);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue