bpo-33584: Fix several minor bugs in asyncio. (GH-7003)
Fix the following bugs in the C implementation: * get_future_loop() silenced all exceptions raised when look up the get_loop attribute, not just an AttributeError. * enter_task() silenced all exceptions raised when look up the current task, not just a KeyError. * repr() was called for a borrowed link in enter_task() and task_step_impl(). * str() was used instead of repr() in formatting one error message (in Python implementation too). * There where few reference leaks in error cases.
This commit is contained in:
parent
4151061855
commit
6655354afc
|
@ -261,7 +261,7 @@ class Task(futures._PyFuture): # Inherit Python Task implementation
|
|||
# Yielding a generator is just wrong.
|
||||
new_exc = RuntimeError(
|
||||
f'yield was used instead of yield from for '
|
||||
f'generator in task {self!r} with {result}')
|
||||
f'generator in task {self!r} with {result!r}')
|
||||
self._loop.call_soon(
|
||||
self.__step, new_exc, context=self._context)
|
||||
else:
|
||||
|
|
|
@ -201,6 +201,7 @@ get_future_loop(PyObject *fut)
|
|||
|
||||
_Py_IDENTIFIER(get_loop);
|
||||
_Py_IDENTIFIER(_loop);
|
||||
PyObject *getloop;
|
||||
|
||||
if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
|
||||
PyObject *loop = ((FutureObj *)fut)->fut_loop;
|
||||
|
@ -208,14 +209,15 @@ get_future_loop(PyObject *fut)
|
|||
return loop;
|
||||
}
|
||||
|
||||
PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop);
|
||||
if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (getloop != NULL) {
|
||||
PyObject *res = _PyObject_CallNoArg(getloop);
|
||||
Py_DECREF(getloop);
|
||||
return res;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
return _PyObject_GetAttrId(fut, &PyId__loop);
|
||||
}
|
||||
|
||||
|
@ -1877,17 +1879,19 @@ enter_task(PyObject *loop, PyObject *task)
|
|||
}
|
||||
item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
|
||||
if (item != NULL) {
|
||||
Py_INCREF(item);
|
||||
PyErr_Format(
|
||||
PyExc_RuntimeError,
|
||||
"Cannot enter into task %R while another " \
|
||||
"task %R is being executed.",
|
||||
task, item, NULL);
|
||||
Py_DECREF(item);
|
||||
return -1;
|
||||
}
|
||||
if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) {
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2075,6 +2079,7 @@ _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
|
|||
if (loop == Py_None) {
|
||||
loop = get_event_loop();
|
||||
if (loop == NULL) {
|
||||
Py_DECREF(current_task_func);
|
||||
return NULL;
|
||||
}
|
||||
ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
|
||||
|
@ -2107,11 +2112,6 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
|
|||
PyObject *res;
|
||||
PyObject *all_tasks_func;
|
||||
|
||||
all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
|
||||
if (all_tasks_func == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
|
||||
"Task.all_tasks() is deprecated, " \
|
||||
"use asyncio.all_tasks() instead",
|
||||
|
@ -2119,6 +2119,11 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
|
||||
if (all_tasks_func == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
|
||||
Py_DECREF(all_tasks_func);
|
||||
return res;
|
||||
|
@ -2723,6 +2728,7 @@ set_exception:
|
|||
PyObject *add_cb = _PyObject_GetAttrId(
|
||||
result, &PyId_add_done_callback);
|
||||
if (add_cb == NULL) {
|
||||
Py_DECREF(wrapper);
|
||||
goto fail;
|
||||
}
|
||||
PyObject *stack[2];
|
||||
|
@ -2788,19 +2794,19 @@ set_exception:
|
|||
}
|
||||
if (res == 1) {
|
||||
/* `result` is a generator */
|
||||
PyObject *ret;
|
||||
ret = task_set_error_soon(
|
||||
o = task_set_error_soon(
|
||||
task, PyExc_RuntimeError,
|
||||
"yield was used instead of yield from for "
|
||||
"generator in task %R with %S", task, result);
|
||||
"generator in task %R with %R", task, result);
|
||||
Py_DECREF(result);
|
||||
return ret;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* The `result` is none of the above */
|
||||
Py_DECREF(result);
|
||||
return task_set_error_soon(
|
||||
o = task_set_error_soon(
|
||||
task, PyExc_RuntimeError, "Task got bad yield: %R", result);
|
||||
Py_DECREF(result);
|
||||
return o;
|
||||
|
||||
self_await:
|
||||
o = task_set_error_soon(
|
||||
|
|
Loading…
Reference in New Issue