mirror of
https://github.com/python/cpython.git
synced 2025-11-03 03:22:27 +00:00
bpo-32591: Add native coroutine origin tracking (#5250)
* Add coro.cr_origin and sys.set_coroutine_origin_tracking_depth * Use coroutine origin information in the unawaited coroutine warning * Stop using set_coroutine_wrapper in asyncio debug mode * In BaseEventLoop.set_debug, enable debugging in the correct thread
This commit is contained in:
parent
1211c9a989
commit
fc2f407829
20 changed files with 485 additions and 100 deletions
|
|
@ -1153,6 +1153,53 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_PyErr_WarnUnawaitedCoroutine(PyObject *coro)
|
||||
{
|
||||
/* First, we attempt to funnel the warning through
|
||||
warnings._warn_unawaited_coroutine.
|
||||
|
||||
This could raise an exception, due to:
|
||||
- a bug
|
||||
- some kind of shutdown-related brokenness
|
||||
- succeeding, but with an "error" warning filter installed, so the
|
||||
warning is converted into a RuntimeWarning exception
|
||||
|
||||
In the first two cases, we want to print the error (so we know what it
|
||||
is!), and then print a warning directly as a fallback. In the last
|
||||
case, we want to print the error (since it's the warning!), but *not*
|
||||
do a fallback. And after we print the error we can't check for what
|
||||
type of error it was (because PyErr_WriteUnraisable clears it), so we
|
||||
need a flag to keep track.
|
||||
|
||||
Since this is called from __del__ context, it's careful to never raise
|
||||
an exception.
|
||||
*/
|
||||
_Py_IDENTIFIER(_warn_unawaited_coroutine);
|
||||
int warned = 0;
|
||||
PyObject *fn = get_warnings_attr(&PyId__warn_unawaited_coroutine, 1);
|
||||
if (fn) {
|
||||
PyObject *res = PyObject_CallFunctionObjArgs(fn, coro, NULL);
|
||||
Py_DECREF(fn);
|
||||
if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
|
||||
warned = 1;
|
||||
}
|
||||
Py_XDECREF(res);
|
||||
}
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_WriteUnraisable(coro);
|
||||
}
|
||||
if (!warned) {
|
||||
PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
|
||||
"coroutine '%.50S' was never awaited",
|
||||
((PyCoroObject *)coro)->cr_qualname);
|
||||
/* Maybe *that* got converted into an exception */
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_WriteUnraisable(coro);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(warn_explicit_doc,
|
||||
"Low-level inferface to warnings functionality.");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue