forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite go2rtc binary handling to be async (home-assistant#128078)
- Loading branch information
Showing
5 changed files
with
116 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,70 @@ | ||
"""Go2rtc server.""" | ||
|
||
from __future__ import annotations | ||
|
||
import asyncio | ||
import logging | ||
import subprocess | ||
from tempfile import NamedTemporaryFile | ||
from threading import Thread | ||
|
||
from .const import DOMAIN | ||
from homeassistant.core import HomeAssistant | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
_TERMINATE_TIMEOUT = 5 | ||
|
||
|
||
def _create_temp_file() -> str: | ||
"""Create temporary config file.""" | ||
# Set delete=False to prevent the file from being deleted when the file is closed | ||
# Linux is clearing tmp folder on reboot, so no need to delete it manually | ||
with NamedTemporaryFile(prefix="go2rtc", suffix=".yaml", delete=False) as file: | ||
return file.name | ||
|
||
|
||
async def _log_output(process: asyncio.subprocess.Process) -> None: | ||
"""Log the output of the process.""" | ||
assert process.stdout is not None | ||
|
||
async for line in process.stdout: | ||
_LOGGER.debug(line[:-1].decode().strip()) | ||
|
||
|
||
class Server(Thread): | ||
"""Server thread.""" | ||
class Server: | ||
"""Go2rtc server.""" | ||
|
||
def __init__(self, binary: str) -> None: | ||
def __init__(self, hass: HomeAssistant, binary: str) -> None: | ||
"""Initialize the server.""" | ||
super().__init__(name=DOMAIN, daemon=True) | ||
self._hass = hass | ||
self._binary = binary | ||
self._stop_requested = False | ||
self._process: asyncio.subprocess.Process | None = None | ||
|
||
def run(self) -> None: | ||
"""Run the server.""" | ||
async def start(self) -> None: | ||
"""Start the server.""" | ||
_LOGGER.debug("Starting go2rtc server") | ||
self._stop_requested = False | ||
with ( | ||
NamedTemporaryFile(prefix="go2rtc", suffix=".yaml") as file, | ||
subprocess.Popen( | ||
[self._binary, "-c", "webrtc.ice_servers=[]", "-c", file.name], | ||
stdout=subprocess.PIPE, | ||
stderr=subprocess.STDOUT, | ||
) as process, | ||
): | ||
while not self._stop_requested and process.poll() is None: | ||
assert process.stdout | ||
line = process.stdout.readline() | ||
if line == b"": | ||
break | ||
_LOGGER.debug(line[:-1].decode()) | ||
|
||
_LOGGER.debug("Terminating go2rtc server") | ||
config_file = await self._hass.async_add_executor_job(_create_temp_file) | ||
|
||
self._process = await asyncio.create_subprocess_exec( | ||
self._binary, | ||
"-c", | ||
"webrtc.ice_servers=[]", | ||
"-c", | ||
config_file, | ||
stdout=asyncio.subprocess.PIPE, | ||
stderr=asyncio.subprocess.STDOUT, | ||
) | ||
|
||
self._hass.async_create_background_task( | ||
_log_output(self._process), "Go2rtc log output" | ||
) | ||
|
||
async def stop(self) -> None: | ||
"""Stop the server.""" | ||
if self._process: | ||
_LOGGER.debug("Stopping go2rtc server") | ||
process = self._process | ||
self._process = None | ||
process.terminate() | ||
try: | ||
process.wait(timeout=5) | ||
except subprocess.TimeoutExpired: | ||
_LOGGER.warning("Go2rtc server didn't terminate gracefully.Killing it") | ||
await asyncio.wait_for(process.wait(), timeout=_TERMINATE_TIMEOUT) | ||
except TimeoutError: | ||
_LOGGER.warning("Go2rtc server didn't terminate gracefully. Killing it") | ||
process.kill() | ||
_LOGGER.debug("Go2rtc server has been stopped") | ||
|
||
def stop(self) -> None: | ||
"""Stop the server.""" | ||
self._stop_requested = True | ||
if self.is_alive(): | ||
self.join() | ||
else: | ||
_LOGGER.debug("Go2rtc server has been stopped") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters