[Python-checkins] bpo-33584: Fix several minor bugs in asyncio. (GH-7003) (GH-7005)
Serhiy Storchaka
webhook-mailer at python.org
Sun May 20 10:34:31 EDT 2018
https://github.com/python/cpython/commit/52d1741c954448cd9ce3f705402e88211b8d4136
commit: 52d1741c954448cd9ce3f705402e88211b8d4136
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: Serhiy Storchaka <storchaka at gmail.com>
date: 2018-05-20T17:34:28+03:00
summary:
bpo-33584: Fix several minor bugs in asyncio. (GH-7003) (GH-7005)
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.
(cherry picked from commit 6655354afcd116c27486bb5ba1dfa50b369d8d85)
Co-authored-by: Serhiy Storchaka <storchaka at gmail.com>
files:
M Lib/asyncio/tasks.py
M Modules/_asynciomodule.c
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 3590748c477a..5df1af6642e4 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -261,7 +261,7 @@ def __step(self, exc=None):
# 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:
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index d66cc4cf0a5f..6d7249a58009 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -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 @@ task_step_impl(TaskObj *task, PyObject *exc)
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 @@ task_step_impl(TaskObj *task, PyObject *exc)
}
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(
More information about the Python-checkins
mailing list