-
-
Notifications
You must be signed in to change notification settings - Fork 37.2k
Use Unix socket for Supervisor communication #163907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 24 commits
275374e
68d94ba
c588908
72db92b
b6be7a1
c3be74c
95d76e8
f499a0b
ea556d6
cccb252
da29f06
fdde931
88b9e6c
d93b45f
58d8824
f0c56d7
03817cc
63bc456
0888dcc
4ce712b
b975a89
2d67754
8f886ae
4bd744f
d4e71ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,7 +11,13 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import Any, Final | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from aiohttp import hdrs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from aiohttp.web import Application, Request, StreamResponse, middleware | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from aiohttp.web import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Application, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HTTPInternalServerError, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Request, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StreamResponse, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| middleware, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import jwt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from jwt import api_jws | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from yarl import URL | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -20,14 +26,20 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.auth.const import GROUP_ID_READ_ONLY | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.auth.models import User | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.components import websocket_api | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.const import HASSIO_USER_NAME | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.core import HomeAssistant, callback | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.helpers.http import current_request | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.helpers.json import json_bytes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.helpers.network import is_cloud_connection | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.helpers.storage import Store | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from homeassistant.util.network import is_local | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .const import KEY_AUTHENTICATED, KEY_HASS_REFRESH_TOKEN_ID, KEY_HASS_USER | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .const import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| KEY_AUTHENTICATED, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| KEY_HASS_REFRESH_TOKEN_ID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| KEY_HASS_USER, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| is_supervisor_unix_socket_request, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER = logging.getLogger(__name__) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -57,7 +69,9 @@ def async_sign_path( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if refresh_token_id is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if use_content_user: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| refresh_token_id = hass.data[STORAGE_KEY] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif connection := websocket_api.current_connection.get(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| connection := websocket_api.current_connection.get() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) and connection.refresh_token_id: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| refresh_token_id = connection.refresh_token_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request := current_request.get() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -117,7 +131,7 @@ def async_user_not_allowed_do_auth( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return "User cannot authenticate remotely" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def async_setup_auth( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def async_setup_auth( # noqa: C901 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hass: HomeAssistant, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| app: Application, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
frenck marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -207,14 +221,53 @@ def async_validate_signed_request(request: Request) -> bool: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request[KEY_HASS_REFRESH_TOKEN_ID] = refresh_token.id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| supervisor_user_id: str | None = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def async_authenticate_supervisor_unix_socket(request: Request) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Authenticate a request from a Unix socket as the Supervisor user. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The Unix Socket is dedicated and only available to Supervisor. To | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| avoid the extra overhead and round trips for the authentication and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| refresh tokens, we directly authenticate requests from the socket as | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| the Supervisor user. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nonlocal supervisor_user_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Fast path: use cached user ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if supervisor_user_id is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if user := await hass.auth.async_get_user(supervisor_user_id): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request[KEY_HASS_USER] = user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| supervisor_user_id = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+237
to
+241
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Slow path: find the Supervisor user by name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for user in await hass.auth.async_get_users(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if user.system_generated and user.name == HASSIO_USER_NAME: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| supervisor_user_id = user.id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Not setting KEY_HASS_REFRESH_TOKEN_ID since Supervisor user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # doesn't use refresh tokens. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request[KEY_HASS_USER] = user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+225
to
+249
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def async_authenticate_unix_socket(request: Request) -> bool: | |
| """Authenticate a request from a Unix socket as the Supervisor user.""" | |
| nonlocal supervisor_user_id | |
| # Fast path: use cached user ID | |
| if supervisor_user_id is not None: | |
| if user := await hass.auth.async_get_user(supervisor_user_id): | |
| request[KEY_HASS_USER] = user | |
| return True | |
| supervisor_user_id = None | |
| # Slow path: find the Supervisor user by name | |
| for user in await hass.auth.async_get_users(): | |
| if user.system_generated and user.name == HASSIO_USER_NAME: | |
| supervisor_user_id = user.id | |
| request[KEY_HASS_USER] = user | |
| supervisor_refresh_token_id: str | None = None | |
| async def async_authenticate_unix_socket(request: Request) -> bool: | |
| """Authenticate a request from a Unix socket as the Supervisor user.""" | |
| nonlocal supervisor_user_id, supervisor_refresh_token_id | |
| # Fast path: use cached user and refresh token IDs | |
| if supervisor_user_id is not None and supervisor_refresh_token_id is not None: | |
| user = await hass.auth.async_get_user(supervisor_user_id) | |
| refresh_token = hass.auth.async_get_refresh_token( | |
| supervisor_refresh_token_id | |
| ) | |
| if user is not None and refresh_token is not None: | |
| request[KEY_HASS_USER] = user | |
| request[KEY_HASS_REFRESH_TOKEN_ID] = refresh_token.id | |
| return True | |
| supervisor_user_id = None | |
| supervisor_refresh_token_id = None | |
| # Slow path: find the Supervisor user by name and associate a refresh token | |
| for user in await hass.auth.async_get_users(): | |
| if user.system_generated and user.name == HASSIO_USER_NAME: | |
| # Reuse an existing refresh token for this user if available | |
| refresh_token = next(iter(user.refresh_tokens.values()), None) | |
| if refresh_token is None: | |
| # Without a refresh token ID, we cannot safely authenticate | |
| return False | |
| supervisor_user_id = user.id | |
| supervisor_refresh_token_id = refresh_token.id | |
| request[KEY_HASS_USER] = user | |
| request[KEY_HASS_REFRESH_TOKEN_ID] = refresh_token.id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer if we can avoid setting KEY_HASS_REFRESH_TOKEN_ID. From what I can tell, the two possible locations seem safe for the Supervisor case:
- onboarding/views.py:286 — IntegrationOnboardingView.post() — requires auth, only called by the frontend during onboarding. Would KeyError on a Unix socket request, but Supervisor has no reason to call this.
- auth.py:71 — async_sign_path() — uses KEY_HASS_REFRESH_TOKEN_ID in request (with an in check, not direct access), so it gracefully falls back to the content user if the key isn't present. Safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason we want to avoid setting KEY_HASS_REFRESH_TOKEN_ID?
I'd suggest to add a comment here explaining we intentionally don't set KEY_HASS_REFRESH_TOKEN_ID.
WRT to the IntegrationOnboardingView it seems there's some missing error handling there and it should check that there's a KEY_HASS_REFRESH_TOKEN_ID in the request? Could it be added to the schema, or is that wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason we want to avoid setting
KEY_HASS_REFRESH_TOKEN_ID?
Really only to avoid having to maintain a "fake" authentication and refresh token. I've added a comment.
WRT to the
IntegrationOnboardingViewit seems there's some missing error handling there and it should check that there's aKEY_HASS_REFRESH_TOKEN_IDin the request? Could it be added to the schema, or is that wrong?
The schema is for payload, but KEY_HASS_REFRESH_TOKEN_ID is data added to the request by our authentication system. So no, we can't add this to schema. The Supervisor should never use this view though, and the view is only active during onboarding. I've added a check for completeness.
edenhaus marked this conversation as resolved.
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,8 @@ | |||||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import asyncio | ||||||||||||||||||||||||
| from pathlib import Path | ||||||||||||||||||||||||
| import socket | ||||||||||||||||||||||||
| from ssl import SSLContext | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| from aiohttp import web | ||||||||||||||||||||||||
|
|
@@ -68,3 +70,62 @@ async def start(self) -> None: | |||||||||||||||||||||||
| reuse_address=self._reuse_address, | ||||||||||||||||||||||||
| reuse_port=self._reuse_port, | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| class HomeAssistantUnixSite(web.BaseSite): | ||||||||||||||||||||||||
| """HomeAssistant specific aiohttp UnixSite. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Listens on a Unix socket for local inter-process communication, | ||||||||||||||||||||||||
| used for Supervisor to Core communication. | ||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| __slots__ = ("_path",) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def __init__( | ||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||
| runner: web.BaseRunner, | ||||||||||||||||||||||||
| path: Path, | ||||||||||||||||||||||||
| *, | ||||||||||||||||||||||||
| backlog: int = 128, | ||||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||||
| """Initialize HomeAssistantUnixSite.""" | ||||||||||||||||||||||||
| super().__init__( | ||||||||||||||||||||||||
| runner, | ||||||||||||||||||||||||
| backlog=backlog, | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| self._path = path | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||
| def name(self) -> str: | ||||||||||||||||||||||||
| """Return server URL.""" | ||||||||||||||||||||||||
| return f"http://unix:{self._path}:" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def _create_unix_socket(self) -> socket.socket: | ||||||||||||||||||||||||
| """Create and bind a Unix domain socket. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Performs blocking filesystem I/O (mkdir, unlink, chmod) and is | ||||||||||||||||||||||||
| intended to be run in an executor. Permissions are set after bind | ||||||||||||||||||||||||
| but before the socket is handed to the event loop, so no | ||||||||||||||||||||||||
| connections can arrive on an unrestricted socket. | ||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||
| self._path.parent.mkdir(parents=True, exist_ok=True) | ||||||||||||||||||||||||
| self._path.unlink(missing_ok=True) | ||||||||||||||||||||||||
| sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||
| sock.bind(str(self._path)) | ||||||||||||||||||||||||
| self._path.chmod(0o600) | ||||||||||||||||||||||||
| except OSError: | ||||||||||||||||||||||||
| sock.close() | ||||||||||||||||||||||||
| raise | ||||||||||||||||||||||||
| return sock | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| async def start(self) -> None: | ||||||||||||||||||||||||
| """Start server.""" | ||||||||||||||||||||||||
| await super().start() | ||||||||||||||||||||||||
| loop = asyncio.get_running_loop() | ||||||||||||||||||||||||
| sock = await loop.run_in_executor(None, self._create_unix_socket) | ||||||||||||||||||||||||
| server = self._runner.server | ||||||||||||||||||||||||
| assert server is not None | ||||||||||||||||||||||||
| self._server = await loop.create_unix_server( | ||||||||||||||||||||||||
| server, sock=sock, backlog=self._backlog | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
agners marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+129
to
+131
|
||||||||||||||||||||||||
| self._server = await loop.create_unix_server( | |
| server, sock=sock, backlog=self._backlog | |
| ) | |
| try: | |
| self._server = await loop.create_unix_server( | |
| server, sock=sock, backlog=self._backlog | |
| ) | |
| except Exception: | |
| sock.close() | |
| self._path.unlink(missing_ok=True) | |
| raise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_create_unix_socket() handles stale entries gracefully. This seems unnecessary to me.
Uh oh!
There was an error while loading. Please reload this page.