summaryrefslogtreecommitdiff
path: root/src/buildstream/_scheduler/scheduler.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildstream/_scheduler/scheduler.py')
-rw-r--r--src/buildstream/_scheduler/scheduler.py20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/buildstream/_scheduler/scheduler.py b/src/buildstream/_scheduler/scheduler.py
index ca7e9279c..0bcbb7182 100644
--- a/src/buildstream/_scheduler/scheduler.py
+++ b/src/buildstream/_scheduler/scheduler.py
@@ -25,6 +25,7 @@ import asyncio
from itertools import chain
import signal
import datetime
+import sys
# Local imports
from .resources import Resources
@@ -188,6 +189,9 @@ class Scheduler:
# Add timeouts
self.loop.call_later(1, self._tick)
+ # Add exception handler
+ self.loop.set_exception_handler(self._handle_exception)
+
# Handle unix signals while running
self._connect_signals()
@@ -596,6 +600,22 @@ class Scheduler:
# as we don't want to pickle exceptions between processes
raise ValueError("Unrecognised notification type received")
+ def _handle_exception(self, loop, context: dict) -> None:
+ e = context.get("exception")
+ exc = bool(e)
+ if e is None:
+ # https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_exception_handler
+ # If no optional Exception generate a generic exception with message value.
+ # exc will be False, instructing the global handler to skip formatting the
+ # assumed exception & related traceback.
+ e = Exception(str(context.get("message")) + " asyncio exception handler called, but no Exception() given")
+
+ # Call the sys global exception handler directly, as to avoid the default
+ # async handler raising an unhandled exception here. App will treat this
+ # as a 'BUG', format it appropriately & exit. mypy needs to ignore parameter
+ # types here as we're overriding sys globally in App._global_exception_handler()
+ sys.excepthook(type(e), e, e.__traceback__, exc) # type: ignore
+
def __getstate__(self):
# The only use-cases for pickling in BuildStream at the time of writing
# are enabling the 'spawn' method of starting child processes, and