[llvm] 6f8c450 - [lit] Cleanly exit on user keyboard interrupt
Julian Lettner via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 3 13:04:47 PDT 2020
Author: Julian Lettner
Date: 2020-04-03T13:03:44-07:00
New Revision: 6f8c45067b1d8d18a669302c0a14d37a230fbc42
URL: https://github.com/llvm/llvm-project/commit/6f8c45067b1d8d18a669302c0a14d37a230fbc42
DIFF: https://github.com/llvm/llvm-project/commit/6f8c45067b1d8d18a669302c0a14d37a230fbc42.diff
LOG: [lit] Cleanly exit on user keyboard interrupt
Graceful lit shutdown on user keyboard interrupt [Ctrl+C] was a
longstanding goal of mine. After a few refactorings this revision
finally enables it. We use the following strategy to deal with
KeyboardInterrupt:
https://noswap.com/blog/python-multiprocessing-keyboardinterrupt
Printing of a helpful summary for interrupted runs (just as the one for
completed runs) will be tackled in future revisions.
Reviewed By: serge-sans-paille, rnk
Differential Revision: https://reviews.llvm.org/D77365
Added:
Modified:
llvm/utils/lit/lit/main.py
llvm/utils/lit/lit/run.py
llvm/utils/lit/lit/util.py
llvm/utils/lit/lit/worker.py
Removed:
################################################################################
diff --git a/llvm/utils/lit/lit/main.py b/llvm/utils/lit/lit/main.py
index 8ac53dfbad9b..fb45995a6280 100755
--- a/llvm/utils/lit/lit/main.py
+++ b/llvm/utils/lit/lit/main.py
@@ -232,10 +232,6 @@ def execute_in_tmp_dir(run, lit_config):
'TEMP': tmp_dir,
'TEMPDIR': tmp_dir,
})
- # FIXME: If Python does not exit cleanly, this directory will not be cleaned
- # up. We should consider writing the lit pid into the temp directory,
- # scanning for stale temp directories, and deleting temp directories whose
- # lit process has died.
try:
run.execute()
finally:
diff --git a/llvm/utils/lit/lit/run.py b/llvm/utils/lit/lit/run.py
index 2fa8ebfd9feb..fca3fb47fd5e 100644
--- a/llvm/utils/lit/lit/run.py
+++ b/llvm/utils/lit/lit/run.py
@@ -73,16 +73,9 @@ def _execute(self, deadline):
self._increase_process_limit()
- # Start a process pool. Copy over the data shared between all test runs.
- # FIXME: Find a way to capture the worker process stderr. If the user
- # interrupts the workers before we make it into our task callback, they
- # will each raise a KeyboardInterrupt exception and print to stderr at
- # the same time.
pool = multiprocessing.Pool(self.workers, lit.worker.initialize,
(self.lit_config, semaphores))
- self._install_win32_signal_handler(pool)
-
async_results = [
pool.apply_async(lit.worker.execute, args=[test],
callback=self.progress_callback)
@@ -135,13 +128,3 @@ def _increase_process_limit(self):
# Warn, unless this is Windows, in which case this is expected.
if os.name != 'nt':
self.lit_config.warning('Failed to raise process limit: %s' % ex)
-
- def _install_win32_signal_handler(self, pool):
- if lit.util.win32api is not None:
- def console_ctrl_handler(type):
- print('\nCtrl-C detected, terminating.')
- pool.terminate()
- pool.join()
- lit.util.abort_now()
- return True
- lit.util.win32api.SetConsoleCtrlHandler(console_ctrl_handler, True)
diff --git a/llvm/utils/lit/lit/util.py b/llvm/utils/lit/lit/util.py
index fa752d0e8d6e..ab51988e21ec 100644
--- a/llvm/utils/lit/lit/util.py
+++ b/llvm/utils/lit/lit/util.py
@@ -479,17 +479,3 @@ def killProcessAndChildren(pid):
psutilProc.kill()
except psutil.NoSuchProcess:
pass
-
-
-try:
- import win32api
-except ImportError:
- win32api = None
-
-def abort_now():
- """Abort the current process without doing any exception teardown"""
- sys.stdout.flush()
- if win32api:
- win32api.TerminateProcess(win32api.GetCurrentProcess(), 3)
- else:
- os.kill(0, 9)
diff --git a/llvm/utils/lit/lit/worker.py b/llvm/utils/lit/lit/worker.py
index d4364c3dcca4..95a8578afac9 100644
--- a/llvm/utils/lit/lit/worker.py
+++ b/llvm/utils/lit/lit/worker.py
@@ -5,6 +5,7 @@
For efficiency, we copy all data needed to execute all tests into each worker
and store it in global variables. This reduces the cost of each task.
"""
+import signal
import time
import traceback
@@ -23,6 +24,11 @@ def initialize(lit_config, parallelism_semaphores):
_lit_config = lit_config
_parallelism_semaphores = parallelism_semaphores
+ # We use the following strategy for dealing with Ctrl+C/KeyboardInterrupt in
+ # subprocesses created by the multiprocessing.Pool.
+ # https://noswap.com/blog/python-multiprocessing-keyboardinterrupt
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+
def execute(test):
"""Run one test in a multiprocessing.Pool
@@ -33,16 +39,10 @@ def execute(test):
Arguments and results of this function are pickled, so they should be cheap
to copy.
"""
- try:
- result = _execute_in_parallelism_group(test, _lit_config,
- _parallelism_semaphores)
- test.setResult(result)
- return test
- except KeyboardInterrupt:
- # If a worker process gets an interrupt, abort it immediately.
- lit.util.abort_now()
- except:
- traceback.print_exc()
+ result = _execute_in_parallelism_group(test, _lit_config,
+ _parallelism_semaphores)
+ test.setResult(result)
+ return test
def _execute_in_parallelism_group(test, lit_config, parallelism_semaphores):
@@ -72,8 +72,6 @@ def _execute_test_handle_errors(test, lit_config):
try:
result = test.config.test_format.execute(test, lit_config)
return _adapt_result(result)
- except KeyboardInterrupt:
- raise
except:
if lit_config.debug:
raise
More information about the llvm-commits
mailing list