avocado.job: Change Ctrl+C handling

Instead of sending SIGKILL to child processes right away,
ignore Ctrl+C for a time window of 2 seconds, explaining
to the user that, and that after the ignore window,
new Ctrl+C will send SIGKILL to the children and terminate
the process.

The functional test was removed, and will be re-added
once I figure out how to properly test the interrupt
behavior.
Signed-off-by: NLucas Meneghel Rodrigues <lmr@redhat.com>
上级 bee943e8
...@@ -462,13 +462,30 @@ class Job(object): ...@@ -462,13 +462,30 @@ class Job(object):
self.output_manager.log_fail_header(str(details)) self.output_manager.log_fail_header(str(details))
return error_codes.numeric_status['AVOCADO_JOB_FAIL'] return error_codes.numeric_status['AVOCADO_JOB_FAIL']
except KeyboardInterrupt: except KeyboardInterrupt:
# Sometimes, the children won't stop right away and a second kill_prompt_displayed = False
# Ctrl+C will trigger an error in exit functions of the time_elapsed = 0
# multiprocess module. We'll have to be merciless and send -9 ignore_window = 2.0
for child in multiprocessing.active_children():
os.kill(child.pid, signal.SIGKILL)
self.output_manager.log_header('\n') self.output_manager.log_header('\n')
self.output_manager.log_header('Interrupted by user request') self.output_manager.log_header('Interrupted by user request')
start_time = time.time()
while multiprocessing.active_children():
time_elapsed = time.time() - start_time
try:
time.sleep(0.1)
except KeyboardInterrupt:
if not kill_prompt_displayed:
k_msg = ('Waiting for tests to end. Ignoring Ctrl+C '
'for %d seconds' % ignore_window)
self.output_manager.log_header(k_msg)
k_msg = ('After that, a new Ctrl+C will send a SIGKILL '
'to them')
self.output_manager.log_header(k_msg)
kill_prompt_displayed = True
if time_elapsed < ignore_window:
continue
else:
for child in multiprocessing.active_children():
os.kill(child.pid, signal.SIGKILL)
sys.exit(error_codes.numeric_status['AVOCADO_JOB_INTERRUPTED']) sys.exit(error_codes.numeric_status['AVOCADO_JOB_INTERRUPTED'])
except Exception, details: except Exception, details:
......
...@@ -126,25 +126,6 @@ class RunnerOperationTest(unittest.TestCase): ...@@ -126,25 +126,6 @@ class RunnerOperationTest(unittest.TestCase):
self.assertEqual(result.exit_status, expected_rc, self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %d:\n%s" % (expected_rc, result)) "Avocado did not return rc %d:\n%s" % (expected_rc, result))
def test_runner_interrupt(self):
os.chdir(basedir)
cmd_line = './scripts/avocado run sleeptenmin'
sp = process.SubProcess(cmd_line)
# Let it run for 3 seconds, then send a SIGINT
# (translates to KeyboardInterrupt, that should kill any sp lying around)
sp.wait(timeout=3, sig=signal.SIGINT)
result = sp.result
output = result.stdout + result.stderr
expected_rc = 4
unexpected_rc = 3
self.assertNotEqual(result.exit_status, unexpected_rc,
"Avocado crashed (rc %d):\n%s" % (unexpected_rc, result))
self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %d:\n%s" % (expected_rc, result))
self.assertIn("Interrupted by user request", output,
"Avocado did not display interruption message. "
"Output:\n%s" % output)
def test_silent_output(self): def test_silent_output(self):
os.chdir(basedir) os.chdir(basedir)
cmd_line = './scripts/avocado --silent run sleeptest' cmd_line = './scripts/avocado --silent run sleeptest'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册