Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6655354

Browse files
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.
1 parent 4151061 commit 6655354

2 files changed

Lines changed: 22 additions & 16 deletions

File tree

Lib/asyncio/tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ def __step(self, exc=None):
261261
# Yielding a generator is just wrong.
262262
new_exc = RuntimeError(
263263
f'yield was used instead of yield from for '
264-
f'generator in task {self!r} with {result}')
264+
f'generator in task {self!r} with {result!r}')
265265
self._loop.call_soon(
266266
self.__step, new_exc, context=self._context)
267267
else:

Modules/_asynciomodule.c

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -201,21 +201,23 @@ get_future_loop(PyObject *fut)
201201

202202
_Py_IDENTIFIER(get_loop);
203203
_Py_IDENTIFIER(_loop);
204+
PyObject *getloop;
204205

205206
if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
206207
PyObject *loop = ((FutureObj *)fut)->fut_loop;
207208
Py_INCREF(loop);
208209
return loop;
209210
}
210211

211-
PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop);
212+
if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
213+
return NULL;
214+
}
212215
if (getloop != NULL) {
213216
PyObject *res = _PyObject_CallNoArg(getloop);
214217
Py_DECREF(getloop);
215218
return res;
216219
}
217220

218-
PyErr_Clear();
219221
return _PyObject_GetAttrId(fut, &PyId__loop);
220222
}
221223

@@ -1877,17 +1879,19 @@ enter_task(PyObject *loop, PyObject *task)
18771879
}
18781880
item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
18791881
if (item != NULL) {
1882+
Py_INCREF(item);
18801883
PyErr_Format(
18811884
PyExc_RuntimeError,
18821885
"Cannot enter into task %R while another " \
18831886
"task %R is being executed.",
18841887
task, item, NULL);
1888+
Py_DECREF(item);
18851889
return -1;
18861890
}
1887-
if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) {
1891+
if (PyErr_Occurred()) {
18881892
return -1;
18891893
}
1890-
return 0;
1894+
return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
18911895
}
18921896

18931897

@@ -2075,6 +2079,7 @@ _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
20752079
if (loop == Py_None) {
20762080
loop = get_event_loop();
20772081
if (loop == NULL) {
2082+
Py_DECREF(current_task_func);
20782083
return NULL;
20792084
}
20802085
ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
@@ -2107,18 +2112,18 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
21072112
PyObject *res;
21082113
PyObject *all_tasks_func;
21092114

2110-
all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
2111-
if (all_tasks_func == NULL) {
2112-
return NULL;
2113-
}
2114-
21152115
if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
21162116
"Task.all_tasks() is deprecated, " \
21172117
"use asyncio.all_tasks() instead",
21182118
1) < 0) {
21192119
return NULL;
21202120
}
21212121

2122+
all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
2123+
if (all_tasks_func == NULL) {
2124+
return NULL;
2125+
}
2126+
21222127
res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
21232128
Py_DECREF(all_tasks_func);
21242129
return res;
@@ -2723,6 +2728,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
27232728
PyObject *add_cb = _PyObject_GetAttrId(
27242729
result, &PyId_add_done_callback);
27252730
if (add_cb == NULL) {
2731+
Py_DECREF(wrapper);
27262732
goto fail;
27272733
}
27282734
PyObject *stack[2];
@@ -2788,19 +2794,19 @@ task_step_impl(TaskObj *task, PyObject *exc)
27882794
}
27892795
if (res == 1) {
27902796
/* `result` is a generator */
2791-
PyObject *ret;
2792-
ret = task_set_error_soon(
2797+
o = task_set_error_soon(
27932798
task, PyExc_RuntimeError,
27942799
"yield was used instead of yield from for "
2795-
"generator in task %R with %S", task, result);
2800+
"generator in task %R with %R", task, result);
27962801
Py_DECREF(result);
2797-
return ret;
2802+
return o;
27982803
}
27992804

28002805
/* The `result` is none of the above */
2801-
Py_DECREF(result);
2802-
return task_set_error_soon(
2806+
o = task_set_error_soon(
28032807
task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2808+
Py_DECREF(result);
2809+
return o;
28042810

28052811
self_await:
28062812
o = task_set_error_soon(

0 commit comments

Comments
 (0)