improve handling of exceptions in plugins

Exceptions generated when invoking a plugin's `collect()` method were being lost when `concurrent.futures.Future.result()` was invoked, since the caught exception would have a traceback relative to the parent thread, not the child.  So we store the original traceback on the exception within the child thread before re-raising, and then extract and display that traceback when the exception is finally caught by the parent.

We also now abort when the exception is found.