|
12 | 12 | import logging |
13 | 13 | import os |
14 | 14 | import sys |
| 15 | +import warnings |
15 | 16 | from collections import deque |
16 | 17 | from signal import Signals |
17 | 18 | from typing import Any, Callable, Deque, List |
|
22 | 23 | debug, info, warn = (logger.debug, logger.info, logger.warning,) |
23 | 24 |
|
24 | 25 | loop_cls = asyncio.SelectorEventLoop |
| 26 | + |
25 | 27 | if os.name == 'nt': |
| 28 | + import msvcrt # pylint: disable=import-error |
26 | 29 | from asyncio.windows_utils import PipeHandle # type: ignore[attr-defined] |
27 | | - import msvcrt |
28 | 30 |
|
29 | 31 | # On windows use ProactorEventLoop which support pipes and is backed by the |
30 | 32 | # more powerful IOCP facility |
31 | 33 | # NOTE: we override in the stdio case, because it doesn't work. |
32 | 34 | loop_cls = asyncio.ProactorEventLoop # type: ignore[attr-defined,misc] |
33 | 35 |
|
| 36 | + # Workaround for a bug in Proactor-based pipe transport: |
| 37 | + # - python/cpython#83413 ("Event loop is closed") which is fixed by |
| 38 | + # python/cpython#92841 in python 3.10.6+ |
| 39 | + # Solution: monkey-patch _ProactorBasePipeTransport. |
| 40 | + # pylint: disable=protected-access |
| 41 | + if sys.version_info < (3, 10, 6): |
| 42 | + from asyncio.proactor_events import _ProactorBasePipeTransport |
| 43 | + |
| 44 | + def __del__(self): # noqa |
| 45 | + if self._sock is not None: |
| 46 | + warnings.warn(f"unclosed transport {self!r}", |
| 47 | + ResourceWarning, source=self) |
| 48 | + self._sock.close() |
| 49 | + |
| 50 | + _ProactorBasePipeTransport.__del__ = __del__ # type: ignore # noqa |
| 51 | + del __del__, _ProactorBasePipeTransport |
| 52 | + # pylint: enable=protected-access |
| 53 | + |
34 | 54 |
|
35 | 55 | class AsyncioEventLoop(BaseEventLoop, asyncio.Protocol, |
36 | 56 | asyncio.SubprocessProtocol): |
|
0 commit comments