mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									4151061855
								
							
						
					
					
						commit
						6655354afc
					
				
					 2 changed files with 22 additions and 16 deletions
				
			
		| 
						 | 
					@ -261,7 +261,7 @@ def __step(self, exc=None):
 | 
				
			||||||
                # Yielding a generator is just wrong.
 | 
					                # Yielding a generator is just wrong.
 | 
				
			||||||
                new_exc = RuntimeError(
 | 
					                new_exc = RuntimeError(
 | 
				
			||||||
                    f'yield was used instead of yield from for '
 | 
					                    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._loop.call_soon(
 | 
				
			||||||
                    self.__step, new_exc, context=self._context)
 | 
					                    self.__step, new_exc, context=self._context)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -201,6 +201,7 @@ get_future_loop(PyObject *fut)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _Py_IDENTIFIER(get_loop);
 | 
					    _Py_IDENTIFIER(get_loop);
 | 
				
			||||||
    _Py_IDENTIFIER(_loop);
 | 
					    _Py_IDENTIFIER(_loop);
 | 
				
			||||||
 | 
					    PyObject *getloop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
 | 
					    if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
 | 
				
			||||||
        PyObject *loop = ((FutureObj *)fut)->fut_loop;
 | 
					        PyObject *loop = ((FutureObj *)fut)->fut_loop;
 | 
				
			||||||
| 
						 | 
					@ -208,14 +209,15 @@ get_future_loop(PyObject *fut)
 | 
				
			||||||
        return loop;
 | 
					        return loop;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop);
 | 
					    if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (getloop != NULL) {
 | 
					    if (getloop != NULL) {
 | 
				
			||||||
        PyObject *res = _PyObject_CallNoArg(getloop);
 | 
					        PyObject *res = _PyObject_CallNoArg(getloop);
 | 
				
			||||||
        Py_DECREF(getloop);
 | 
					        Py_DECREF(getloop);
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PyErr_Clear();
 | 
					 | 
				
			||||||
    return _PyObject_GetAttrId(fut, &PyId__loop);
 | 
					    return _PyObject_GetAttrId(fut, &PyId__loop);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1877,17 +1879,19 @@ enter_task(PyObject *loop, PyObject *task)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
 | 
					    item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
 | 
				
			||||||
    if (item != NULL) {
 | 
					    if (item != NULL) {
 | 
				
			||||||
 | 
					        Py_INCREF(item);
 | 
				
			||||||
        PyErr_Format(
 | 
					        PyErr_Format(
 | 
				
			||||||
            PyExc_RuntimeError,
 | 
					            PyExc_RuntimeError,
 | 
				
			||||||
            "Cannot enter into task %R while another " \
 | 
					            "Cannot enter into task %R while another " \
 | 
				
			||||||
            "task %R is being executed.",
 | 
					            "task %R is being executed.",
 | 
				
			||||||
            task, item, NULL);
 | 
					            task, item, NULL);
 | 
				
			||||||
 | 
					        Py_DECREF(item);
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) {
 | 
					    if (PyErr_Occurred()) {
 | 
				
			||||||
        return -1;
 | 
					        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) {
 | 
					    if (loop == Py_None) {
 | 
				
			||||||
        loop = get_event_loop();
 | 
					        loop = get_event_loop();
 | 
				
			||||||
        if (loop == NULL) {
 | 
					        if (loop == NULL) {
 | 
				
			||||||
 | 
					            Py_DECREF(current_task_func);
 | 
				
			||||||
            return NULL;
 | 
					            return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ret = PyObject_CallFunctionObjArgs(current_task_func, loop, 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 *res;
 | 
				
			||||||
    PyObject *all_tasks_func;
 | 
					    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,
 | 
					    if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
 | 
				
			||||||
                     "Task.all_tasks() is deprecated, " \
 | 
					                     "Task.all_tasks() is deprecated, " \
 | 
				
			||||||
                     "use asyncio.all_tasks() instead",
 | 
					                     "use asyncio.all_tasks() instead",
 | 
				
			||||||
| 
						 | 
					@ -2119,6 +2119,11 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
 | 
				
			||||||
        return NULL;
 | 
					        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);
 | 
					    res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
 | 
				
			||||||
    Py_DECREF(all_tasks_func);
 | 
					    Py_DECREF(all_tasks_func);
 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
| 
						 | 
					@ -2723,6 +2728,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
 | 
				
			||||||
                PyObject *add_cb = _PyObject_GetAttrId(
 | 
					                PyObject *add_cb = _PyObject_GetAttrId(
 | 
				
			||||||
                    result, &PyId_add_done_callback);
 | 
					                    result, &PyId_add_done_callback);
 | 
				
			||||||
                if (add_cb == NULL) {
 | 
					                if (add_cb == NULL) {
 | 
				
			||||||
 | 
					                    Py_DECREF(wrapper);
 | 
				
			||||||
                    goto fail;
 | 
					                    goto fail;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                PyObject *stack[2];
 | 
					                PyObject *stack[2];
 | 
				
			||||||
| 
						 | 
					@ -2788,19 +2794,19 @@ task_step_impl(TaskObj *task, PyObject *exc)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (res == 1) {
 | 
					    if (res == 1) {
 | 
				
			||||||
        /* `result` is a generator */
 | 
					        /* `result` is a generator */
 | 
				
			||||||
        PyObject *ret;
 | 
					        o = task_set_error_soon(
 | 
				
			||||||
        ret = task_set_error_soon(
 | 
					 | 
				
			||||||
            task, PyExc_RuntimeError,
 | 
					            task, PyExc_RuntimeError,
 | 
				
			||||||
            "yield was used instead of yield from for "
 | 
					            "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);
 | 
					        Py_DECREF(result);
 | 
				
			||||||
        return ret;
 | 
					        return o;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* The `result` is none of the above */
 | 
					    /* The `result` is none of the above */
 | 
				
			||||||
    Py_DECREF(result);
 | 
					    o = task_set_error_soon(
 | 
				
			||||||
    return task_set_error_soon(
 | 
					 | 
				
			||||||
        task, PyExc_RuntimeError, "Task got bad yield: %R", result);
 | 
					        task, PyExc_RuntimeError, "Task got bad yield: %R", result);
 | 
				
			||||||
 | 
					    Py_DECREF(result);
 | 
				
			||||||
 | 
					    return o;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
self_await:
 | 
					self_await:
 | 
				
			||||||
    o = task_set_error_soon(
 | 
					    o = task_set_error_soon(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue