mirror of
https://git.rtems.org/rtems-tools/
synced 2025-10-19 08:21:31 +08:00
tester: Correctly handle contro-c.
Add support to kill running tests if the user presses control-c.
This commit is contained in:
@@ -116,6 +116,7 @@ class execute(object):
|
||||
self.environment = None
|
||||
self.outputting = False
|
||||
self.timing_out = False
|
||||
self.proc = None
|
||||
|
||||
def _capture(self, command, proc, timeout = None):
|
||||
"""Create 3 threads to read stdout and stderr and send to the output handler
|
||||
@@ -262,12 +263,25 @@ class execute(object):
|
||||
timeout_thread.daemon = True
|
||||
timeout_thread.start()
|
||||
try:
|
||||
self.lock.acquire()
|
||||
try:
|
||||
self.proc = proc
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
self.lock.release()
|
||||
exitcode = proc.wait()
|
||||
except:
|
||||
print 'killing'
|
||||
proc.kill()
|
||||
raise
|
||||
finally:
|
||||
self.lock.acquire()
|
||||
try:
|
||||
self.proc = None
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
self.lock.release()
|
||||
if self.cleanup:
|
||||
self.cleanup(proc)
|
||||
if timeout_thread:
|
||||
@@ -415,6 +429,37 @@ class execute(object):
|
||||
self.environment = environment
|
||||
return old_environment
|
||||
|
||||
def kill(self):
|
||||
self.lock.acquire()
|
||||
try:
|
||||
if self.proc is not None:
|
||||
self.proc.kill()
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
self.lock.release()
|
||||
|
||||
def terminate(self):
|
||||
self.lock.acquire()
|
||||
try:
|
||||
if self.proc is not None:
|
||||
self.proc.terminate()
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
self.lock.release()
|
||||
|
||||
def send_signal(self, signal):
|
||||
self.lock.acquire()
|
||||
try:
|
||||
if self.proc is not None:
|
||||
print "sending sig"
|
||||
self.proc.send_signal(signal)
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
self.lock.release()
|
||||
|
||||
class capture_execution(execute):
|
||||
"""Capture all output as a string and return it."""
|
||||
|
||||
|
43
rtemstoolkit/stacktraces.py
Normal file
43
rtemstoolkit/stacktraces.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2013-2014 Chris Johns (chrisj@rtems.org)
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of the RTEMS Tools package in 'rtems-tools'.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
def trace():
|
||||
code = []
|
||||
for threadId, stack in sys._current_frames().items():
|
||||
code.append("\n# thread-id: %s" % threadId)
|
||||
for filename, lineno, name, line in traceback.extract_stack(stack):
|
||||
code.append('file: "%s", line %d, in %s' % (filename, lineno, name))
|
||||
if line:
|
||||
code.append(" %s" % (line.strip()))
|
||||
return '\n'.join(code)
|
||||
|
41
tester/rt/bsps.py
Normal file
41
tester/rt/bsps.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2013-2014 Chris Johns (chrisj@rtems.org)
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of the RTEMS Tools package in 'rtems-tools'.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
from rtemstoolkit import error
|
||||
from rtemstoolkit import log
|
||||
from rtemstoolkit import path
|
||||
|
||||
def list(opts):
|
||||
path_ = opts.defaults.expand('%%{_configdir}/bsps/*.mc')
|
||||
bsps = path.collect_files(path_)
|
||||
log.notice(' BSP List:')
|
||||
for bsp in bsps:
|
||||
log.notice(' %s' % (path.basename(bsp[:-3])))
|
||||
raise error.exit()
|
@@ -62,7 +62,7 @@ class file(config.file):
|
||||
self.console = None
|
||||
self.output = None
|
||||
self.report = report
|
||||
self.load(name)
|
||||
self.name = name
|
||||
|
||||
def __del__(self):
|
||||
if self.console:
|
||||
@@ -181,6 +181,9 @@ class file(config.file):
|
||||
for l in text:
|
||||
print ' '.join(l)
|
||||
|
||||
def run(self):
|
||||
self.load(self.name)
|
||||
|
||||
def capture(self, text):
|
||||
text = [(']', l) for l in text.replace(chr(13), '').splitlines()]
|
||||
self._lock()
|
||||
@@ -203,3 +206,7 @@ class file(config.file):
|
||||
if flag in dt.split(','):
|
||||
return True
|
||||
return False
|
||||
|
||||
def kill(self):
|
||||
if self.process:
|
||||
self.process.kill()
|
||||
|
@@ -38,7 +38,9 @@ import time
|
||||
from rtemstoolkit import error
|
||||
from rtemstoolkit import log
|
||||
from rtemstoolkit import path
|
||||
from rtemstoolkit import stacktraces
|
||||
|
||||
import bsps
|
||||
import config
|
||||
import console
|
||||
import options
|
||||
@@ -46,17 +48,6 @@ import report
|
||||
import version
|
||||
import fnmatch
|
||||
|
||||
def stacktraces():
|
||||
import traceback
|
||||
code = []
|
||||
for threadId, stack in sys._current_frames().items():
|
||||
code.append("\n# thread-id: %s" % threadId)
|
||||
for filename, lineno, name, line in traceback.extract_stack(stack):
|
||||
code.append('file: "%s", line %d, in %s' % (filename, lineno, name))
|
||||
if line:
|
||||
code.append(" %s" % (line.strip()))
|
||||
return '\n'.join(code)
|
||||
|
||||
class test(object):
|
||||
def __init__(self, index, total, report, executable, rtems_tools, bsp, bsp_config, opts):
|
||||
self.index = index
|
||||
@@ -78,7 +69,15 @@ class test(object):
|
||||
if not path.isdir(rtems_tools_bin):
|
||||
raise error.general('cannot find RTEMS tools path: %s' % (rtems_tools_bin))
|
||||
self.opts.defaults['rtems_tools'] = rtems_tools_bin
|
||||
self.config = config.file(report, bsp_config, self.opts)
|
||||
self.config = config.file(self.report, self.bsp_config, self.opts)
|
||||
|
||||
def run(self):
|
||||
if self.config:
|
||||
self.config.run()
|
||||
|
||||
def kill(self):
|
||||
if self.config:
|
||||
self.config.kill()
|
||||
|
||||
class test_run(object):
|
||||
def __init__(self, index, total, report, executable, rtems_tools, bsp, bsp_config, opts):
|
||||
@@ -102,6 +101,7 @@ class test_run(object):
|
||||
self.executable, self.rtems_tools,
|
||||
self.bsp, self.bsp_config,
|
||||
self.opts)
|
||||
self.test.run()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except:
|
||||
@@ -120,6 +120,10 @@ class test_run(object):
|
||||
if self.result is not None:
|
||||
raise self.result[0], self.result[1], self.result[2]
|
||||
|
||||
def kill(self):
|
||||
if self.test:
|
||||
self.test.kill()
|
||||
|
||||
def find_executables(paths, glob):
|
||||
executables = []
|
||||
for p in paths:
|
||||
@@ -175,8 +179,13 @@ def list_bsps(opts):
|
||||
log.notice(' %s' % (path.basename(bsp[:-3])))
|
||||
raise error.exit()
|
||||
|
||||
def killall(tests):
|
||||
for test in tests:
|
||||
test.kill()
|
||||
|
||||
def run(command_path = None):
|
||||
import sys
|
||||
tests = []
|
||||
stdtty = console.save()
|
||||
opts = None
|
||||
default_exefilter = '*.exe'
|
||||
@@ -194,7 +203,7 @@ def run(command_path = None):
|
||||
command_path = command_path)
|
||||
log.notice('RTEMS Testing - Tester, v%s' % (version.str()))
|
||||
if opts.find_arg('--list-bsps'):
|
||||
list_bsps(opts)
|
||||
bsps.list(opts)
|
||||
exe_filter = opts.find_arg('--filter')
|
||||
if exe_filter:
|
||||
exe_filter = exe_filter[1]
|
||||
@@ -246,7 +255,6 @@ def run(command_path = None):
|
||||
reporting = 1
|
||||
jobs = int(opts.jobs(opts.defaults['_ncpus']))
|
||||
exe = 0
|
||||
tests = []
|
||||
finished = []
|
||||
if jobs > len(executables):
|
||||
jobs = len(executables)
|
||||
@@ -288,7 +296,8 @@ def run(command_path = None):
|
||||
report_finished(reports, report_mode, -1, finished, job_trace)
|
||||
reports.summary()
|
||||
end_time = datetime.datetime.now()
|
||||
log.notice('Testing time: %s' % (str(end_time - start_time)))
|
||||
log.notice('Average test time: %s' % (str((end_time - start_time) / total)))
|
||||
log.notice('Testing time : %s' % (str(end_time - start_time)))
|
||||
except error.general, gerr:
|
||||
print gerr
|
||||
sys.exit(1)
|
||||
@@ -302,8 +311,9 @@ def run(command_path = None):
|
||||
print '}} dumping:', threading.active_count()
|
||||
for t in threading.enumerate():
|
||||
print '}} ', t.name
|
||||
print stacktraces()
|
||||
print stacktraces.trace()
|
||||
log.notice('abort: user terminated')
|
||||
killall(tests)
|
||||
sys.exit(1)
|
||||
finally:
|
||||
console.restore(stdtty)
|
||||
|
Reference in New Issue
Block a user