summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-05-20 13:30:31 (GMT)
committerGitHub <noreply@github.com>2018-05-20 13:30:31 (GMT)
commit6655354afcd116c27486bb5ba1dfa50b369d8d85 (patch)
treea4c2dafd327bc7b1033695108b5bc86c5383145c
parent4151061855b571bf8a7579daa7875b8e243057b9 (diff)
downloadcpython-6655354afcd116c27486bb5ba1dfa50b369d8d85.zip
cpython-6655354afcd116c27486bb5ba1dfa50b369d8d85.tar.gz
cpython-6655354afcd116c27486bb5ba1dfa50b369d8d85.tar.bz2
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.
-rw-r--r--Lib/asyncio/tasks.py2
-rw-r--r--Modules/_asynciomodule.c36
2 files changed, 22 insertions, 16 deletions
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 3590748..5df1af6 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -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:
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index d66cc4c..6d7249a 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 @@ 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(