diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4241e6b8..5fb8ac3b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.12', '3.11', '3.10', '3.9', '3.8', '3.7'] + python-version: ['3.13', '3.12', '3.11', '3.10', '3.9', '3.8', '3.7'] os: ['ubuntu-latest', 'macos-latest', 'windows-latest'] exclude: - os: 'ubuntu-latest' diff --git a/pynvim/msgpack_rpc/event_loop/asyncio.py b/pynvim/msgpack_rpc/event_loop/asyncio.py index cb17f321..9b180248 100644 --- a/pynvim/msgpack_rpc/event_loop/asyncio.py +++ b/pynvim/msgpack_rpc/event_loop/asyncio.py @@ -9,6 +9,11 @@ from collections import deque from signal import Signals from typing import Any, Callable, Deque, List, Optional, cast +from asyncio.unix_events import ThreadedChildWatcher +try: + from asyncio.unix_events import PidfdChildWatcher +except ImportError: + PidfdChildWatcher = None if sys.version_info >= (3, 12): from typing import Final, override @@ -188,11 +193,6 @@ async def connect_stdout(): @override def _connect_child(self, argv: List[str]) -> None: - if os.name != 'nt': - # see #238, #241 - self._child_watcher = asyncio.get_child_watcher() - self._child_watcher.attach_loop(self._loop) - async def create_subprocess(): transport: asyncio.SubprocessTransport # type: ignore transport, protocol = await self._loop.subprocess_exec( @@ -200,6 +200,26 @@ async def create_subprocess(): pid = transport.get_pid() debug("child subprocess_exec successful, PID = %s", pid) + if os.name != 'nt': + # see #238, #241 + pidfd_works = False + if PidfdChildWatcher is not None and hasattr(os, "pidfd_open"): + try: + fd = os.pidfd_open(pid) + except Exception: + pass + else: + os.close(fd) + pidfd_works = True + + if pidfd_works: + watcher = PidfdChildWatcher() + else: + watcher = ThreadedChildWatcher() + + watcher.attach_loop(self._loop) + self._child_watcher = watcher + self._transport = cast(asyncio.WriteTransport, transport.get_pipe_transport(0)) # stdin self._protocol = protocol diff --git a/tox.ini b/tox.ini index d215e606..8010a9eb 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ [tox] min_version = 4.0 envlist = - py{37,38,39,310,311,312}-asyncio + py{37,38,39,310,311,312,313}-asyncio checkqa skip_missing_interpreters = true @@ -18,6 +18,7 @@ python = 3.10: py310 3.11: py311 3.12: py312 + 3.13: py313 pypy3: pypy3 [testenv]