Skip to content

Commit b1e0a11

Browse files
committed
Switch timeouts to use async_timeout
async_timeout does not suffer from the same race problems as asyncio.wait_for see python/cpython#98518 for more details
1 parent 54d174d commit b1e0a11

File tree

4 files changed

+22
-5
lines changed

4 files changed

+22
-5
lines changed

pyhap/camera.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"""
1818

1919
import asyncio
20+
import async_timeout
2021
import functools
2122
import os
2223
import ipaddress
@@ -859,8 +860,8 @@ async def stop_stream(self, session_info):
859860
logger.info('[%s] Stopping stream.', session_id)
860861
try:
861862
ffmpeg_process.terminate()
862-
_, stderr = await asyncio.wait_for(
863-
ffmpeg_process.communicate(), timeout=2.0)
863+
async with async_timeout.timeout(2.0):
864+
_, stderr = await ffmpeg_process.communicate()
864865
logger.debug('Stream command stderr: %s', stderr)
865866
except asyncio.TimeoutError:
866867
logger.error(

pyhap/hap_handler.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
The HAPServerHandler manages the state of the connection and handles incoming requests.
44
"""
55
import asyncio
6+
import async_timeout
67
from http import HTTPStatus
78
import logging
89
from typing import TYPE_CHECKING, Dict, Optional
@@ -93,6 +94,12 @@ class UnprivilegedRequestException(Exception):
9394
pass
9495

9596

97+
async def _run_with_timeout(coro, timeout: float) -> None:
98+
"""Run a coroutine with a timeout."""
99+
async with async_timeout.timeout(timeout):
100+
await coro
101+
102+
96103
class HAPServerHandler:
97104
"""Manages HAP connection state and handles incoming HTTP requests."""
98105

@@ -820,7 +827,7 @@ def handle_resource(self) -> None:
820827
'does not define a "get_snapshot" or "async_get_snapshot" method'
821828
)
822829

823-
task = asyncio.ensure_future(asyncio.wait_for(coro, RESPONSE_TIMEOUT))
830+
task = asyncio.ensure_future(_run_with_timeout(coro, RESPONSE_TIMEOUT))
824831
self.send_response(HTTPStatus.OK)
825832
self.send_header("Content-Type", "image/jpeg")
826833
assert self.response is not None # nosec

pyhap/util.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import async_timeout
23
import base64
34
import functools
45
import random
@@ -135,7 +136,8 @@ async def event_wait(event, timeout):
135136
:rtype: bool
136137
"""
137138
try:
138-
await asyncio.wait_for(event.wait(), timeout)
139+
async with async_timeout.timeout(timeout):
140+
await event.wait()
139141
except asyncio.TimeoutError:
140142
pass
141143
return event.is_set()

setup.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@
2222
README = f.read()
2323

2424

25-
REQUIRES = ["cryptography", "chacha20poly1305-reuseable", "orjson>=3.7.2", "zeroconf>=0.36.2", "h11"]
25+
REQUIRES = [
26+
"async_timeout",
27+
"cryptography",
28+
"chacha20poly1305-reuseable",
29+
"orjson>=3.7.2",
30+
"zeroconf>=0.36.2",
31+
"h11",
32+
]
2633

2734

2835
setup(

0 commit comments

Comments
 (0)