diff --git a/httpstan/services_stub.py b/httpstan/services_stub.py index 4e1e8a403..1409bd47d 100644 --- a/httpstan/services_stub.py +++ b/httpstan/services_stub.py @@ -15,6 +15,7 @@ import multiprocessing as mp import os import select +import signal import socket import tempfile import typing @@ -26,9 +27,14 @@ import httpstan.services.arguments as arguments from httpstan.config import HTTPSTAN_DEBUG + # Use `get_context` to get a package-specific multiprocessing context. # See "Contexts and start methods" in the `multiprocessing` docs for details. -executor = concurrent.futures.ProcessPoolExecutor(mp_context=mp.get_context("fork")) +def init_worker() -> None: + signal.signal(signal.SIGINT, signal.SIG_IGN) # ignore KeyboardInterrupt + + +executor = concurrent.futures.ProcessPoolExecutor(mp_context=mp.get_context("fork"), initializer=init_worker) logger = logging.getLogger("httpstan") diff --git a/httpstan/views.py b/httpstan/views.py index 738192e5c..c6d61b9e2 100644 --- a/httpstan/views.py +++ b/httpstan/views.py @@ -389,7 +389,11 @@ def _services_call_done(operation: dict, future: asyncio.Future) -> None: operation["result"] = _make_error(message, status=status) # Delete messages associated with the fit. If initialization # fails, for example, messages will exist on disk. Remove them. - httpstan.cache.delete_fit(operation["metadata"]["fit"]["name"]) + try: + httpstan.cache.delete_fit(operation["metadata"]["fit"]["name"]) + except FileNotFoundError: + # occurs when control-c stops sampling + pass else: logger.info(f"Operation `{operation['name']}` finished.") operation["result"] = schemas.Fit().load(operation["metadata"]["fit"])