improve error catching/handling/re-raising

This commit is contained in:
Gregory Becker
2020-01-16 15:45:52 -08:00
committed by Tamara Dahlgren
parent bc486a961c
commit e614cdf007
3 changed files with 48 additions and 22 deletions

View File

@@ -880,16 +880,21 @@ def child_process(child_pipe, input_stream):
package_context = get_package_context(tb)
build_log = None
if hasattr(pkg, 'log_path'):
if context == 'build' and hasattr(pkg, 'log_path'):
build_log = pkg.log_path
test_log = None
if context == 'test':
test_log = os.path.join(os.getcwd(), pkg.test_log_name)
# make a pickleable exception to send to parent.
msg = "%s: %s" % (exc_type.__name__, str(exc))
ce = ChildError(msg,
exc_type.__module__,
exc_type.__name__,
tb_string, build_log, package_context)
tb_string, package_context,
build_log, test_log)
child_pipe.send(ce)
finally:
@@ -1050,14 +1055,15 @@ class ChildError(InstallError):
# context instead of Python context.
build_errors = [('spack.util.executable', 'ProcessError')]
def __init__(self, msg, module, classname, traceback_string, build_log,
context):
def __init__(self, msg, module, classname, traceback_string, context,
build_log, test_log):
super(ChildError, self).__init__(msg)
self.module = module
self.name = classname
self.traceback = traceback_string
self.build_log = build_log
self.context = context
self.build_log = build_log
self.test_log = test_log
@property
def long_message(self):
@@ -1066,22 +1072,29 @@ def long_message(self):
if (self.module, self.name) in ChildError.build_errors:
# The error happened in some external executed process. Show
# the build log with errors or warnings highlighted.
if self.build_log and os.path.exists(self.build_log):
errors, warnings = parse_log_events(self.build_log)
# the log with errors or warnings highlighted.
def write_log_summary(log_type, log):
errors, warnings = parse_log_events(log)
nerr = len(errors)
nwar = len(warnings)
if nerr > 0:
# If errors are found, only display errors
out.write(
"\n%s found in build log:\n" % plural(nerr, 'error'))
"\n%s found in %s log:\n" %
(plural(nerr, 'error'), log_type))
out.write(make_log_context(errors))
elif nwar > 0:
# If no errors are found but warnings are, display warnings
out.write(
"\n%s found in build log:\n" % plural(nwar, 'warning'))
"\n%s found in %s log:\n" %
(plural(nwar, 'warning'), log_type))
out.write(make_log_context(warnings))
if self.build_log and os.path.exists(self.build_log):
write_log_summary('build', self.build_log)
if self.test_log and os.path.exists(self.test_log):
write_log_summary('test', self.test_log)
else:
# The error happened in in the Python code, so try to show
# some context from the Package itself.
@@ -1097,6 +1110,10 @@ def long_message(self):
out.write('See build log for details:\n')
out.write(' %s\n' % self.build_log)
if self.test_log and os.path.exists(self.test_log):
out.write('See test log for details:\n')
out.write(' %s\n' % self.test_log)
return out.getvalue()
def __str__(self):
@@ -1113,13 +1130,16 @@ def __reduce__(self):
self.module,
self.name,
self.traceback,
self.context,
self.build_log,
self.context)
self.test_log)
def _make_child_error(msg, module, name, traceback, build_log, context):
def _make_child_error(msg, module, name, traceback, context,
build_log, test_log):
"""Used by __reduce__ in ChildError to reconstruct pickled errors."""
return ChildError(msg, module, name, traceback, build_log, context)
return ChildError(msg, module, name, traceback, context,
build_log, test_log)
class StopPhase(spack.error.SpackError):

View File

@@ -1615,21 +1615,25 @@ def test_process():
print('Error: %s: %s' % (exc_type.__name__,
getattr(e, 'message',
'No error message')))
# construct arguments to re-raise error from type
args = []
if hasattr(e, 'message'):
args.append(e.message)
if hasattr(e, 'long_message'):
args.append(e.long_message)
if sys.version_info[0] < 3:
# ugly hack: exec to avoid the fact this is a syntax
# error in python 3
exec("raise exc_type, None, traceback",
exec("raise exc_type(*args), None, traceback",
globals(), locals())
else:
raise exc_type().with_traceback(traceback)
raise exc_type(*args).with_traceback(traceback)
tty.set_debug(old_debug)
try:
spack.build_environment.fork(
self, test_process, dirty=dirty, fake=False, context='test')
except Exception as e:
tty.error('Tests failed. See test log for details\n'
' %s\n' % test_log_file)
spack.build_environment.fork(
self, test_process, dirty=dirty, fake=False, context='test')
def test(self):
pass