catch ^C at startup time while models are being scanned

This commit is contained in:
Lincoln Stein 2024-03-21 23:50:52 -04:00 committed by psychedelicious
parent 2ecbb9f720
commit 34f5259980
2 changed files with 24 additions and 10 deletions

View File

@ -85,7 +85,7 @@ class DownloadQueueService(DownloadQueueServiceBase):
self._logger.info(f"Waiting for {len(active_jobs)} active download jobs to complete") self._logger.info(f"Waiting for {len(active_jobs)} active download jobs to complete")
with self._queue.mutex: with self._queue.mutex:
self._queue.queue.clear() self._queue.queue.clear()
self.join() # wait for all active jobs to finish self.cancel_all_jobs()
self._stop_event.set() self._stop_event.set()
for thread in self._worker_pool: for thread in self._worker_pool:
thread.join() thread.join()

View File

@ -2,6 +2,7 @@
import os import os
import re import re
import signal
import threading import threading
import time import time
from hashlib import sha256 from hashlib import sha256
@ -112,6 +113,18 @@ class ModelInstallService(ModelInstallServiceBase):
# makes the installer harder to use outside the web app # makes the installer harder to use outside the web app
def start(self, invoker: Optional[Invoker] = None) -> None: def start(self, invoker: Optional[Invoker] = None) -> None:
"""Start the installer thread.""" """Start the installer thread."""
# Yes, this is weird. When the installer thread is running, the
# thread masks the ^C signal. When we receive a
# sigINT, we stop the thread, reset sigINT, and send a new
# sigINT to the parent process.
def sigint_handler(signum, frame):
self.stop()
signal.signal(signal.SIGINT, signal.SIG_DFL)
signal.raise_signal(signal.SIGINT)
signal.signal(signal.SIGINT, sigint_handler)
with self._lock: with self._lock:
if self._running: if self._running:
raise Exception("Attempt to start the installer service twice") raise Exception("Attempt to start the installer service twice")
@ -122,15 +135,16 @@ class ModelInstallService(ModelInstallServiceBase):
def stop(self, invoker: Optional[Invoker] = None) -> None: def stop(self, invoker: Optional[Invoker] = None) -> None:
"""Stop the installer thread; after this the object can be deleted and garbage collected.""" """Stop the installer thread; after this the object can be deleted and garbage collected."""
with self._lock: # do manual acquire() so as to receive signals
if not self._running: if not self._running:
raise Exception("Attempt to stop the install service before it was started") raise Exception("Attempt to stop the install service before it was started")
self._stop_event.set() self._logger.debug("calling stop_event.set()")
self._clear_pending_jobs() self._stop_event.set()
self._download_cache.clear() self._clear_pending_jobs()
assert self._install_thread is not None self._download_cache.clear()
self._install_thread.join() assert self._install_thread is not None
self._running = False self._install_thread.join()
self._running = False
def _clear_pending_jobs(self) -> None: def _clear_pending_jobs(self) -> None:
for job in self.list_jobs(): for job in self.list_jobs():