|
50 | 50 | from typing import Union, Any, Type, Optional, Callable, TypeVar, Tuple, Awaitable
|
51 | 51 |
|
52 | 52 | if typing.TYPE_CHECKING:
|
53 |
| - from typing import Dict, List # noqa: F401 |
| 53 | + from typing import Dict, List, Set # noqa: F401 |
54 | 54 |
|
55 | 55 | from typing_extensions import Protocol
|
56 | 56 | else:
|
@@ -159,6 +159,18 @@ async def main():
|
159 | 159 | # In Python 3, _ioloop_for_asyncio maps from asyncio loops to IOLoops.
|
160 | 160 | _ioloop_for_asyncio = dict() # type: Dict[asyncio.AbstractEventLoop, IOLoop]
|
161 | 161 |
|
| 162 | + # Maintain a set of all pending tasks to follow the warning in the docs |
| 163 | + # of asyncio.create_tasks: |
| 164 | + # https://docs.python.org/3.11/library/asyncio-task.html#asyncio.create_task |
| 165 | + # This ensures that all pending tasks have a strong reference so they |
| 166 | + # will not be garbage collected before they are finished. |
| 167 | + # (Thus avoiding "task was destroyed but it is pending" warnings) |
| 168 | + # An analogous change has been proposed in cpython for 3.13: |
| 169 | + # https://github.com/python/cpython/issues/91887 |
| 170 | + # If that change is accepted, this can eventually be removed. |
| 171 | + # If it is not, we will consider the rationale and may remove this. |
| 172 | + _pending_tasks = set() # type: Set[Future] |
| 173 | + |
162 | 174 | @classmethod
|
163 | 175 | def configure(
|
164 | 176 | cls, impl: "Union[None, str, Type[Configurable]]", **kwargs: Any
|
@@ -805,6 +817,12 @@ def close_fd(self, fd: Union[int, _Selectable]) -> None:
|
805 | 817 | except OSError:
|
806 | 818 | pass
|
807 | 819 |
|
| 820 | + def _register_task(self, f: Future) -> None: |
| 821 | + self._pending_tasks.add(f) |
| 822 | + |
| 823 | + def _unregister_task(self, f: Future) -> None: |
| 824 | + self._pending_tasks.discard(f) |
| 825 | + |
808 | 826 |
|
809 | 827 | class _Timeout(object):
|
810 | 828 | """An IOLoop timeout, a UNIX timestamp and a callback"""
|
|
0 commit comments