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:
Serhiy Storchaka 2018-05-20 16:30:31 +03:00 committed by GitHub
parent 4151061855
commit 6655354afc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 16 deletions

View File

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

View File

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