Skip to content

Commit

Permalink
Inline try_wait_one using asyncio.wait_for
Browse files Browse the repository at this point in the history
Although the former accepts multiple awaitables, it is only ever called
with a single one, so just use `wait_for` instead.

Additionally, the `try_wait_one` fails in Python 3.11, as
`Process.wait()` returns a coroutine, and `asyncio.wait` only accepts
tasks, so it errors out.
  • Loading branch information
QuLogic authored and nirbheek committed Aug 8, 2022
1 parent ec8023b commit 5c2703b
Showing 1 changed file with 7 additions and 8 deletions.
15 changes: 7 additions & 8 deletions mesonbuild/mtest.py
Expand Up @@ -16,6 +16,7 @@

from pathlib import Path
from collections import deque
from contextlib import suppress
from copy import deepcopy
import argparse
import asyncio
Expand Down Expand Up @@ -1161,11 +1162,6 @@ def check_testdata(objs: T.List[TestSerialisation]) -> T.List[TestSerialisation]

# Custom waiting primitives for asyncio

async def try_wait_one(*awaitables: T.Any, timeout: T.Optional[T.Union[int, float]]) -> None:
"""Wait for completion of one of the given futures, ignoring timeouts."""
await asyncio.wait(awaitables,
timeout=timeout, return_when=asyncio.FIRST_COMPLETED)

async def queue_iter(q: 'asyncio.Queue[T.Optional[str]]') -> T.AsyncIterator[str]:
while True:
item = await q.get()
Expand Down Expand Up @@ -1273,21 +1269,24 @@ async def _kill(self) -> T.Optional[str]:

# Make sure the termination signal actually kills the process
# group, otherwise retry with a SIGKILL.
await try_wait_one(p.wait(), timeout=0.5)
with suppress(TimeoutError):
await asyncio.wait_for(p.wait(), timeout=0.5)
if p.returncode is not None:
return None

os.killpg(p.pid, signal.SIGKILL)

await try_wait_one(p.wait(), timeout=1)
with suppress(TimeoutError):
await asyncio.wait_for(p.wait(), timeout=1)
if p.returncode is not None:
return None

# An earlier kill attempt has not worked for whatever reason.
# Try to kill it one last time with a direct call.
# If the process has spawned children, they will remain around.
p.kill()
await try_wait_one(p.wait(), timeout=1)
with suppress(TimeoutError):
await asyncio.wait_for(p.wait(), timeout=1)
if p.returncode is not None:
return None
return 'Test process could not be killed.'
Expand Down

0 comments on commit 5c2703b

Please sign in to comment.