Reduce verbosity of error messages when concretizing environments (#26843)
With this commit stacktraces of subprocesses are shown only if debug mode is active
This commit is contained in:
parent
26b58701bc
commit
56209cb114
@ -1161,7 +1161,8 @@ def _concretize_separately(self, tests=False):
|
||||
tty.msg(msg)
|
||||
|
||||
concretized_root_specs = spack.util.parallel.parallel_map(
|
||||
_concretize_task, arguments, max_processes=max_processes
|
||||
_concretize_task, arguments, max_processes=max_processes,
|
||||
debug=tty.is_debug()
|
||||
)
|
||||
|
||||
finish = time.time()
|
||||
|
@ -10,8 +10,6 @@
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import six
|
||||
|
||||
from .cpus import cpus_available
|
||||
|
||||
|
||||
@ -28,11 +26,16 @@ def __init__(self, exc_cls, exc, tb):
|
||||
exc: exception raised from the worker process
|
||||
"""
|
||||
self.pid = os.getpid()
|
||||
self.error_message = ''.join(traceback.format_exception(exc_cls, exc, tb))
|
||||
self.error_message = str(exc)
|
||||
self.stacktrace_message = ''.join(traceback.format_exception(exc_cls, exc, tb))
|
||||
|
||||
@property
|
||||
def stacktrace(self):
|
||||
msg = "[PID={0.pid}] {0.stacktrace_message}"
|
||||
return msg.format(self)
|
||||
|
||||
def __str__(self):
|
||||
msg = "[PID={0.pid}] {0.error_message}"
|
||||
return msg.format(self)
|
||||
return self.error_message
|
||||
|
||||
|
||||
class Task(object):
|
||||
@ -53,29 +56,31 @@ def __call__(self, *args, **kwargs):
|
||||
return value
|
||||
|
||||
|
||||
def raise_if_errors(*results):
|
||||
def raise_if_errors(*results, **kwargs):
|
||||
"""Analyze results from worker Processes to search for ErrorFromWorker
|
||||
objects. If found print all of them and raise an exception.
|
||||
|
||||
Args:
|
||||
*results: results from worker processes
|
||||
debug: if True show complete stacktraces
|
||||
|
||||
Raise:
|
||||
RuntimeError: if ErrorFromWorker objects are in the results
|
||||
"""
|
||||
err_stream = six.StringIO() # sys.stderr
|
||||
debug = kwargs.get('debug', False) # This can be a keyword only arg in Python 3
|
||||
errors = [x for x in results if isinstance(x, ErrorFromWorker)]
|
||||
if not errors:
|
||||
return
|
||||
|
||||
# Report the errors and then raise
|
||||
for error in errors:
|
||||
print(error, file=err_stream)
|
||||
msg = '\n'.join([
|
||||
error.stacktrace if debug else str(error) for error in errors
|
||||
])
|
||||
|
||||
print('[PARENT PROCESS]:', file=err_stream)
|
||||
traceback.print_stack(file=err_stream)
|
||||
error_msg = 'errors occurred in worker processes:\n{0}'
|
||||
raise RuntimeError(error_msg.format(err_stream.getvalue()))
|
||||
error_fmt = '{0}'
|
||||
if len(errors) > 1 and not debug:
|
||||
error_fmt = 'errors occurred during concretization of the environment:\n{0}'
|
||||
|
||||
raise RuntimeError(error_fmt.format(msg))
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
@ -108,13 +113,15 @@ def num_processes(max_processes=None):
|
||||
return min(cpus_available(), max_processes)
|
||||
|
||||
|
||||
def parallel_map(func, arguments, max_processes=None):
|
||||
def parallel_map(func, arguments, max_processes=None, debug=False):
|
||||
"""Map a task object to the list of arguments, return the list of results.
|
||||
|
||||
Args:
|
||||
func (Task): user defined task object
|
||||
arguments (list): list of arguments for the task
|
||||
max_processes (int or None): maximum number of processes allowed
|
||||
debug (bool): if False, raise an exception containing just the error messages
|
||||
from workers, if True an exception with complete stacktraces
|
||||
|
||||
Raises:
|
||||
RuntimeError: if any error occurred in the worker processes
|
||||
@ -125,5 +132,5 @@ def parallel_map(func, arguments, max_processes=None):
|
||||
results = p.map(task_wrapper, arguments)
|
||||
else:
|
||||
results = list(map(task_wrapper, arguments))
|
||||
raise_if_errors(*results)
|
||||
raise_if_errors(*results, debug=debug)
|
||||
return results
|
||||
|
Loading…
Reference in New Issue
Block a user