From edb6f3ba1fc5d704364ec97dec9ef32580c2164f Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Apr 18 2025 16:40:41 +0000 Subject: Add a default timeout on socket objects Currently sockets aren't created with timeouts and the service occasionally hangs. This doesn't fix the underlying bug, but it should ensure the service never gets permanently stuck waiting on socket operations. The value of the timeout was chosen arbitrarily and is hopefully absurdly high. Some packages take a very long time to sign so we might need to bump this. Signed-off-by: Jeremy Cline --- diff --git a/src/bridge.py b/src/bridge.py index 6d33548..278aa20 100644 --- a/src/bridge.py +++ b/src/bridge.py @@ -1425,6 +1425,11 @@ def bridge_one_request(config, server_listen_sock, client_listen_sock): client_sock.close() finally: server_sock.close() + # Python 3.10 made this a deprecated alias of TimeoutError so it's only a matter of + # time before they remove this alias and break everyone. Replace this with TimeoutError + # when upgrading to support Python 3.10+ + except socket.timeout: + logging.exception('Socket timeout occurred') except InvalidRequestError as e: logging.warning('Invalid request: %s', str(e)) except InvalidReplyError as e: @@ -1447,6 +1452,8 @@ def bridge_one_request(config, server_listen_sock, client_listen_sock): def main(): + # Any blocking socket operations time out after an hour + socket.setdefaulttimeout(60 * 60) options = utils.get_daemon_options('A signing server bridge', '~/.sigul/bridge.conf') utils.setup_logging(options, 'bridge') diff --git a/src/client.py b/src/client.py index 51cadfb..f7a7121 100644 --- a/src/client.py +++ b/src/client.py @@ -1927,6 +1927,8 @@ def handle_global_options(): def main(): + # Any blocking socket operations time out after an hour + socket.setdefaulttimeout(60 * 60) child_exception = None try: (config, handler, args) = handle_global_options() diff --git a/src/server.py b/src/server.py index f27a5d0..c7f51b7 100644 --- a/src/server.py +++ b/src/server.py @@ -2731,7 +2731,7 @@ def request_handling_child(config): except InvalidRequestError as e: logging.warning('Invalid request: %s', str(e)) except (IOError, socket.error) as e: - logging.info('I/O error: %s', repr(e)) + logging.exception('I/O error: %s', repr(e)) except nss.error.NSPRError as e: if e.errno == nss.error.PR_CONNECT_RESET_ERROR: logging.debug('NSPR error: Connection reset') @@ -2759,6 +2759,8 @@ def request_handling_child(config): def main(): + # Any blocking socket operations time out after an hour + socket.setdefaulttimeout(60 * 60) options = utils.get_daemon_options('A signing server', '~/.sigul/server.conf') utils.setup_logging(options, 'server')