diff --git a/problemtools/context.py b/problemtools/context.py index ab705d2b..28022246 100644 --- a/problemtools/context.py +++ b/problemtools/context.py @@ -32,5 +32,9 @@ def submit_background_work(self, job: Callable[_P, _T], *args: _P.args, **kwargs assert self.executor self._background_work.append(self.executor.submit(job, *args, **kwargs)) + def cancel_background_work(self) -> None: + for future in self._background_work: + future.cancel() + def wait_for_background_work(self) -> None: concurrent.futures.wait(self._background_work) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 378e6d8d..f2771b62 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -1485,6 +1485,11 @@ def check(self, context: Context) -> tuple[int, int]: item.check(context) except VerifyError: pass + except KeyboardInterrupt: + # In multithreaded runs, we can queue up large chunks of work. If the + # user presses ctrl-c, we want to cancel that to exit quickly. + context.cancel_background_work() + raise finally: # Wait for background work to finish before performing an rmtree on # the directory tree it uses.