Skip to content

Commit

Permalink
Merge pull request #1435 from pbiering/fix-1313
Browse files Browse the repository at this point in the history
Fix 1313 by rework server listen code
  • Loading branch information
pbiering authored Mar 13, 2024
2 parents 5b99b5a + f508af5 commit 50e8f1e
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 38 deletions.
2 changes: 1 addition & 1 deletion radicale/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def shutdown_signal_handler(signal_number: int,
server.serve(configuration, shutdown_socket_out)
except Exception as e:
logger.critical("An exception occurred during server startup: %s", e,
exc_info=True)
exc_info=False)
sys.exit(1)


Expand Down
51 changes: 14 additions & 37 deletions radicale/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Copyright © 2008 Pascal Halter
# Copyright © 2008-2017 Guillaume Ayoub
# Copyright © 2017-2019 Unrud <[email protected]>
# Copyright © 2024-2024 Peter Bieringer <[email protected]>
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -22,7 +23,6 @@
"""

import errno
import http
import select
import socket
Expand Down Expand Up @@ -283,45 +283,22 @@ def serve(configuration: config.Configuration,
servers = {}
try:
hosts: List[Tuple[str, int]] = configuration.get("server", "hosts")
for address in hosts:
# Try to bind sockets for IPv4 and IPv6
possible_families = (socket.AF_INET, socket.AF_INET6)
bind_ok = False
for i, family in enumerate(possible_families):
is_last = i == len(possible_families) - 1
for AddressPort in hosts:
# retrieve IPv4/IPv6 address of address
try:
getaddrinfo = socket.getaddrinfo(AddressPort[0], AddressPort[1], 0, socket.SOCK_STREAM, socket.IPPROTO_TCP)
except OSError as e:
logger.warn("cannot retrieve IPv4 or IPv6 address of '%s': %s" % (format_address(AddressPort), e))
continue
logger.debug("getaddrinfo of '%s': %s" % (format_address(AddressPort), getaddrinfo))
for (AddressFamily, SocketKind, SocketProto, SocketFlags, SocketAddress) in getaddrinfo:
logger.debug("try to create server socket on '%s'" % (format_address(SocketAddress)))
try:
server = server_class(configuration, family, address,
RequestHandler)
server = server_class(configuration, AddressFamily, (SocketAddress[0], SocketAddress[1]), RequestHandler)
except OSError as e:
# Ignore unsupported families (only one must work)
if ((bind_ok or not is_last) and (
isinstance(e, socket.gaierror) and (
# Hostname does not exist or doesn't have
# address for address family
# Linux: temporary failure in name resolution (-3)
e.errno == socket.EAI_AGAIN or
# macOS: IPv6 address for INET address family
e.errno == socket.EAI_NONAME or
# Address not for address family
e.errno == COMPAT_EAI_ADDRFAMILY or
e.errno == COMPAT_EAI_NODATA) or
# Workaround for PyPy
str(e) == "address family mismatched" or
# Address family not available (e.g. IPv6 disabled)
# macOS: IPv4 address for INET6 address family with
# IPV6_V6ONLY set
e.errno == errno.EADDRNOTAVAIL or
# Device or resource busy (16)
e.errno == errno.EBUSY or
# Address family not supported
e.errno == errno.EAFNOSUPPORT or
# Protocol not supported
e.errno == errno.EPROTONOSUPPORT)):
continue
raise RuntimeError("Failed to start server %r: %s" % (
format_address(address), e)) from e
logger.warn("cannot create server socket on '%s': %s" % (format_address(SocketAddress), e))
continue
servers[server.socket] = server
bind_ok = True
server.set_app(application)
logger.info("Listening on %r%s",
format_address(server.server_address),
Expand Down

0 comments on commit 50e8f1e

Please sign in to comment.