Browse Source

Catch and handle exceptions during startup

Richard van der Hoff 2 years ago
parent
commit
aac8c9c6e5
3 changed files with 21 additions and 12 deletions
  1. 10 1
      synapse/app/_base.py
  2. 8 4
      synapse/app/generic_worker.py
  3. 3 7
      synapse/app/homeserver.py

+ 10 - 1
synapse/app/_base.py

@@ -143,7 +143,7 @@ def start_reactor(
 
 def quit_with_error(error_string: str) -> NoReturn:
     message_lines = error_string.split("\n")
-    line_length = max(len(line) for line in message_lines if len(line) < 80) + 2
+    line_length = min(max(len(line) for line in message_lines), 80) + 2
     sys.stderr.write("*" * line_length + "\n")
     for line in message_lines:
         sys.stderr.write(" %s\n" % (line.rstrip(),))
@@ -151,6 +151,15 @@ def quit_with_error(error_string: str) -> NoReturn:
     sys.exit(1)
 
 
+def handle_startup_exception(e: Exception) -> NoReturn:
+    # Exceptions that occur between setting up the logging and forking or starting
+    # the reactor are written to the logs, followed by a summary to stderr.
+    logger.exception("Exception during startup")
+    quit_with_error(
+        f"Error during initialisation:\n   {e}\nThere may be more information in the logs."
+    )
+
+
 def redirect_stdio_to_logs() -> None:
     streams = [("stdout", LogLevel.info), ("stderr", LogLevel.error)]
 

+ 8 - 4
synapse/app/generic_worker.py

@@ -33,6 +33,7 @@ from synapse.api.urls import (
 )
 from synapse.app import _base
 from synapse.app._base import (
+    handle_startup_exception,
     max_request_body_size,
     redirect_stdio_to_logs,
     register_start,
@@ -469,11 +470,14 @@ def start(config_options):
 
     setup_logging(hs, config, use_worker_options=True)
 
-    hs.setup()
+    try:
+        hs.setup()
 
-    # Ensure the replication streamer is always started in case we write to any
-    # streams. Will no-op if no streams can be written to by this worker.
-    hs.get_replication_streamer()
+        # Ensure the replication streamer is always started in case we write to any
+        # streams. Will no-op if no streams can be written to by this worker.
+        hs.get_replication_streamer()
+    except Exception as e:
+        handle_startup_exception(e)
 
     register_start(_base.start, hs)
 

+ 3 - 7
synapse/app/homeserver.py

@@ -37,10 +37,10 @@ from synapse.api.urls import (
 )
 from synapse.app import _base
 from synapse.app._base import (
+    handle_startup_exception,
     listen_ssl,
     listen_tcp,
     max_request_body_size,
-    quit_with_error,
     redirect_stdio_to_logs,
     register_start,
 )
@@ -70,8 +70,6 @@ from synapse.rest.synapse.client import build_synapse_client_resource_tree
 from synapse.rest.well_known import WellKnownResource
 from synapse.server import HomeServer
 from synapse.storage import DataStore
-from synapse.storage.engines import IncorrectDatabaseSetup
-from synapse.storage.prepare_database import UpgradeDatabaseException
 from synapse.util.httpresourcetree import create_resource_tree
 from synapse.util.module_loader import load_module
 from synapse.util.versionstring import get_version_string
@@ -359,10 +357,8 @@ def setup(config_options):
 
     try:
         hs.setup()
-    except IncorrectDatabaseSetup as e:
-        quit_with_error(str(e))
-    except UpgradeDatabaseException as e:
-        quit_with_error("Failed to upgrade database: %s" % (e,))
+    except Exception as e:
+        handle_startup_exception(e)
 
     async def do_acme() -> bool:
         """