aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryn M. Reeves <bmr@redhat.com>2018-09-07 12:15:10 -0400
committerBryn M. Reeves <bmr@redhat.com>2018-09-10 15:43:53 +0100
commit9aaba972bf6a42c33ea9bca80f07bfb880ba45a1 (patch)
tree3de02015473f235ce671a979222d50c355bdbaa9
parent5d6228b85e174dee8abcc4c206a1e9034242c6c6 (diff)
downloadsos-9aaba972bf6a42c33ea9bca80f07bfb880ba45a1.tar.gz
[sosreport] trap directly to PDB in handle_exception()
Now that plugins are run in a threadpool, it is not possible to defer the call to pdb.post_mortem() to the top-level exception handler in the main thread: this is due to the fact that in a pool, exceptions are caught and saved to be re-raised to thread calling the pool when results are returned. When the saved exception is raised to the top-level handler the execution context it relates to is gone: the backtrace and stack frame have been torn down and only very limited information is available from the exception frame. Instead, catch these exceptions _inside_ the thread pool context, and directly trap to the Python debugger. This allows plugin code to be debugged interactively with the full backtrace and with all access to local variables and the execution stack. In addition, this means that after the debugger has handled the exception it is possible to return to the run and continue until report completion. One side effect of this change is that the *-plugin-errors.txt file containng the backtrace is now written into the archive whether or not --debug is given. Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
-rw-r--r--sos/sosreport.py9
1 files changed, 8 insertions, 1 deletions
diff --git a/sos/sosreport.py b/sos/sosreport.py
index 44be75a1..77ae7161 100644
--- a/sos/sosreport.py
+++ b/sos/sosreport.py
@@ -30,6 +30,7 @@ from shutil import rmtree
import tempfile
import hashlib
from concurrent.futures import ThreadPoolExecutor, TimeoutError
+import pdb
from sos import _sos as _
from sos import __version__
@@ -504,7 +505,13 @@ class SoSReport(object):
def handle_exception(self, plugname=None, func=None):
if self.raise_plugins or self.exit_process:
- raise
+ # retrieve exception info for the current thread and stack.
+ (etype, val, tb) = sys.exc_info()
+ # we are NOT in interactive mode, print the exception...
+ traceback.print_exception(etype, val, tb, file=sys.stdout)
+ print_()
+ # ...then start the debugger in post-mortem mode.
+ pdb.post_mortem(tb)
if plugname and func:
self._log_plugin_exception(plugname, func)