diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-05-20 13:30:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-20 13:30:31 (GMT) |
commit | 6655354afcd116c27486bb5ba1dfa50b369d8d85 (patch) | |
tree | a4c2dafd327bc7b1033695108b5bc86c5383145c | |
parent | 4151061855b571bf8a7579daa7875b8e243057b9 (diff) | |
download | cpython-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.py | 2 | ||||
-rw-r--r-- | Modules/_asynciomodule.c | 36 |
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( |