• Chris Toshok's avatar
    build tracebacks incrementally while c++ unwinding · 9305f720
    Chris Toshok authored
    Add a tb_next to the BoxedTraceback object, which during normal unwinding is how we add lines to a traceback.
    For getTraceback() we take advantage fo the fact that each BoxedTraceback can have multiple lines in it, and
    only create one.  Also add BoxedTraceback::Here which is kinda like PyTraceback_Here, except that since we
    don't have access to the ExcInfo inside it, we have to pass a pointer to the BoxedTraceback*.
    
    three wrinkles in traceback generation while unwinding are:
    
       1) if the previous frame was an osr frame (so we should skip the current frame)
       2) if the traceback object was passed to raise3, or raise0 was used (treated as a re-raise by cpython)
       3) the interpreter map
    
    1 and 2 are fixed by keeping a per-thread interpreter state variable, "unwind_why" ("why" is probably
    a bad name to use in this context, but cpython's logic uses that word as well), to record if we're in
    either of those cases.  Both cases have the same effect (skip the next traceback line, and reset state
    to NORMAL.)
    
    The interpreter map problem comes about because of the way c++ unwinding works.  since ASTInterpreter::execute
    uses RAII for RegisterHelper, unwinding through the frame causes us to jump to a cleanup block and then resume
    unwinding (with the IP still in ASTInterpreter::execute).  Since the IP is there, we assume the frame is valid
    and we can look up $rbp in the interpreter map.  Given that we just cleaned up the RegisterHelper (and removed
    the $rbp mapping), we crash.
    
    The fix here is to keep the same RegisterHelper in ASTInterpreter::execute, but the ip checked for by the
    unwinder (and the $rbp in the mapping) correspond to ASTInterpreter::executeInner.
    
    Lastly, AST_Interpreter::invoke catches exceptions, so we won't make it to the top-most ASTInterpreter::execute,
    and so won't add the final line.  We make use of BoxedTraceback::Here here as well to add the final line.
    9305f720
traceback.cpp 4.01 KB