2nd iteration fix socket activation
This commit is contained in:
41
server.py
41
server.py
@@ -47,29 +47,30 @@ from middleware.cache_middleware import cache_control
|
|||||||
# Helper --------------------------------------------------------------------
|
# Helper --------------------------------------------------------------------
|
||||||
def _fd_to_socket(fd: int) -> socket.socket:
|
def _fd_to_socket(fd: int) -> socket.socket:
|
||||||
"""
|
"""
|
||||||
Turn a raw file‑descriptor that came from systemd into a *non‑blocking*
|
Convert a file‑descriptor received from systemd into a ready‑to‑use
|
||||||
``socket.socket`` instance that preserves the original family, type and
|
``socket.socket`` object.
|
||||||
protocol.
|
|
||||||
|
|
||||||
The function mirrors the logic used by `sd_listen_fds` in the systemd
|
* The fd already contains the correct address family, socket type and
|
||||||
libraries (see libsystemd/libsystemd/sd-daemon.c). It queries the
|
protocol – passing ``fileno=fd`` makes the constructor adopt them.
|
||||||
kernel for the socket's actual family, type and protocol using
|
* aiohttp (and the rest of the code) expects the socket to be **non‑blocking**,
|
||||||
``getsockopt`` on the fd.
|
so we set that flag explicitly.
|
||||||
|
* Any OSError while wrapping the descriptor is turned into a RuntimeError
|
||||||
|
with a clear message; the caller can log it.
|
||||||
"""
|
"""
|
||||||
# Query the kernel for the family / type / protocol of the fd.
|
try:
|
||||||
# These syscalls are cheap and work for IPv4, IPv6 and Unix sockets.
|
# ``socket.socket`` with the ``fileno`` argument re‑uses the existing OS
|
||||||
family = socket.getsockopt(fd, socket.SOL_SOCKET, socket.SO_DOMAIN)
|
# socket. The resulting object automatically reports the correct
|
||||||
sock_type = socket.getsockopt(fd, socket.SOL_SOCKET, socket.SO_TYPE)
|
# ``family``, ``type`` and ``proto`` attributes.
|
||||||
proto = socket.getsockopt(fd, socket.SOL_SOCKET, socket.SO_PROTOCOL)
|
sock = socket.socket(fileno=fd)
|
||||||
|
|
||||||
# Build the socket object *without* creating a new fd.
|
# aiohttp’s SockSite registers the socket with the event loop, which
|
||||||
# ``socket.socket`` with ``fileno=fd`` re‑uses the existing descriptor.
|
# requires a non‑blocking descriptor.
|
||||||
# ``closefd=False`` tells Python not to close the fd when the socket
|
sock.setblocking(False)
|
||||||
# object is garbage‑collected – systemd will close it when the service
|
|
||||||
# exits.
|
return sock
|
||||||
sock = socket.socket(family=family, type=sock_type, proto=proto, fileno=fd)
|
except OSError as exc:
|
||||||
sock.setblocking(False) # aiohttp expects non‑blocking
|
# Raising a RuntimeError makes the caller’s ``except`` clause simpler.
|
||||||
return sock
|
raise RuntimeError(f"Could not wrap fd {fd} as a socket: {exc}") from exc
|
||||||
|
|
||||||
async def send_socket_catch_exception(function, message):
|
async def send_socket_catch_exception(function, message):
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user