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