From 7f58c4f9eebff5cd955c2e9980091b5d66fc02ec Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 7 Jul 2013 23:30:05 -0400 Subject: [PATCH] Try to improve python crash logging This seems like it should work, but IPython seems to be getting in my way. --- src/Dyna/Backend/Python/errors.py | 64 +++++++++++++++----------- src/Dyna/Backend/Python/interpreter.py | 7 ++- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/Dyna/Backend/Python/errors.py b/src/Dyna/Backend/Python/errors.py index 7d31fb4..f1be8a5 100644 --- a/src/Dyna/Backend/Python/errors.py +++ b/src/Dyna/Backend/Python/errors.py @@ -1,4 +1,4 @@ -import sys +import readline, sys from IPython.core.ultratb import VerboseTB from utils import parse_attrs from config import dotdynadir @@ -26,41 +26,51 @@ class DynaInitializerException(Exception): super(DynaInitializerException, self).__init__(msg) -def exception_handler(etype, evalue, tb): - # once for the log file. - with file(dotdynadir / 'crash.log', 'wb') as crashreport: - h = VerboseTB(color_scheme='Linux', - call_pdb=False, - ostream=crashreport, - long_header=True, - include_vars=True, - check_cache=None) - h(etype, evalue, tb) +def crash_handler(interp): + """ + Use our custom exception handler for handling uncaught exceptions. + """ - show_traceback((etype, evalue, tb)) + def exception_handler(etype, evalue, tb): - # TODO: we should package up all relevant state including compiler - # version, codegen output, interpreter state (possibly without the - # chart -- because it might be too big to email); input to repl. - # This should all go into a tarball. + print 'FATAL ERROR (%s): %s' % (etype.__name__, evalue) - if crash_handler.interp is not None: - crash_handler.interp() + # once for the log file. + with file(dotdynadir / 'crash.log', 'wb') as crashreport: + h = VerboseTB(color_scheme='Linux', + call_pdb=False, + ostream=crashreport, + long_header=True, + include_vars=True, + check_cache=None) + h(etype, evalue, tb) - print 'FATAL ERROR (%s): %s' % (etype.__name__, evalue) - print 'Crash log available %s' % crashreport.name + # Dump the entirety of readline's history. I do not think that + # we can easily distinguish what is this session or a different + # one, but this is more useful than nothing. + # + # XXX Well, that'd be great, except that it doesn't work. -def crash_handler(): - """ - Use our custom exception handler for handling uncaught exceptions. - """ - sys.excepthook = exception_handler + if interp is not None: + if interp._repl is not None: + crashreport.write("REPL history:\n") + for ix in xrange(1,readline.get_current_history_length()): + crashreport.write("%d: %s\n" \ + % (ix,readline.get_history_entry(ix))) + + # TODO: we should package up all relevant state including + # compiler version, codegen output, interpreter state + # (possibly without the chart -- because it might be too big + # to email); input to repl. This should all go into a + # tarball. -# XXX: global state... -crash_handler.interp = None + show_traceback((etype, evalue, tb)) + print 'Crash log available %s' % crashreport.name + + sys.excepthook = exception_handler def show_traceback(einfo=None): if not einfo: diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index b4b54d8..7a7b9f9 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -174,6 +174,8 @@ class Interpreter(object): self.files = [] + self._repl = None + # interpretor needs a place for it's temporary files. self.tmp = tmp = (dotdynadir / 'tmp' / str(os.getpid())) if tmp.exists(): @@ -507,7 +509,8 @@ class Interpreter(object): def repl(self): import repl - repl.REPL(self).cmdloop() + self._repl = repl.REPL(self) + self._repl.cmdloop() def do(self, filename, initialize=True): """ @@ -664,7 +667,7 @@ def main(): interp = Interpreter() - crash_handler() + crash_handler(interp) if args.source: -- 2.50.1