Skip to content

Commit

Permalink
Replace deprecated asyncio.get_child_watcher()
Browse files Browse the repository at this point in the history
Use PidfdChildWatcher if os.pidfd_open is available and works, and
otherwise use ThreadedChildWatcher which should work in any case.

Fixes #583
  • Loading branch information
cryptomilk committed Jan 4, 2025
1 parent 63a0250 commit accf17f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
30 changes: 25 additions & 5 deletions pynvim/msgpack_rpc/event_loop/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -188,18 +193,33 @@ 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(
self._protocol_factory, *argv)
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
Expand Down
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -18,6 +18,7 @@ python =
3.10: py310
3.11: py311
3.12: py312
3.13: py313
pypy3: pypy3

[testenv]
Expand Down

0 comments on commit accf17f

Please sign in to comment.