<div dir="ltr">Well, I've gone and made an attempt at a "less leaky" version. (It became an obsession :( )<div><br><div>Some features:</div><div> - tries not to show internals of swank and abcl debugging calls</div><div> - shows top of exception trace for java exceptions, marked with "!" to indicate they were caught.</div><div> - names local functions, even if we only would see the java frame.</div><div> - And some other nuisances. Read the code?</div><div><br></div><div><br></div><div>I am soliciting beta testers - need to see whether it holds up under stress of use by other.</div><div>You will need to check out my branch of ABCL <a href="https://github.com/alanruttenberg/abcl.git">https://github.com/alanruttenberg/abcl.git</a> - use branch "stage"</div><div>and you will need my branch of slime <a href="https://github.com/alanruttenberg/slime/">https://github.com/alanruttenberg/slime/</a> - use branch "beta" </div><div><br></div><div>Build abcl with: ant abcl-aio.jar</div><div><br></div><div>There are a number of other debugging goodies here, also worth testing:</div><div>- Better inspectors for some things, like java classes</div><div>- View source and disassemble from debugger should work on every frame</div><div>- Most definition sources are recorded, including those compiled in a buffer. </div><div> Try edit definitions 'print-object and you will see all the methods and their source locations</div><div>- slime-edit-callers</div><div><br></div><div>Alan</div><div><br></div><div><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jan 1, 2017 at 6:11 AM, Mark Evenson <span dir="ltr"><<a href="mailto:evenson@panix.com" target="_blank">evenson@panix.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
<br>
On 12/31/16 20:37, Alan Ruttenberg wrote:<br>
> I'm getting backtraces that are noisy and therefore impede comprehension.<br>
><br>
> For example, in the following stack trace, frames 68-4 seem to<br>
> recapitulate, for the most part, the java stack corresponding to frames<br>
> 87-69<br>
<br>
</span>The ABCL backtrace abstraction is perhaps a little bit leaky and noisy<br>
with respect to its representation of Java calls, but it has been useful<br>
in improving the implementation in its present form since Tobias and I<br>
introduced it back in 2006-7 (?).<br>
<br>
My strong claim is that a user of ABCL never will see Java calls in the<br>
backtrace, as they only result in errors in the ABCL implementation<br>
which causes the "Lisp computation" to fail, thunking out into the<br>
surrounding Java Try/Catch/Exception mechanism. So, "normally" (i.e.<br>
when there are more bugs in your code than the implementation), these<br>
verbose, confusing messages are not seen by the user.<br>
<br>
In your example, frames 87-69 show the Lisp-side computation which got<br>
to the error being signaled in the ABCL implmentation. Then frames 4-68<br>
provide the trace of Java attempting to deal with the error signaled by<br>
the JVM when executing Primitives.java:2845. Frames 0-2 show the error<br>
propagating back into the Lisp-side debugger machinery.<br>
<br>
I think the only real information I get as a developer here is that<br>
there is an error occuring in org.armedbear.lisp.Primitives:<wbr>2845; the<br>
rest of the Java calls don't need to be shown. The backtrace from 4-67<br>
can confirm/deny hypothesis about what exacly caused the Java error on<br>
that line, but usually I would figure things out by starting ABCL under<br>
JPDA, setting a break point before Primitives:2845, replicating the<br>
error, and single-stepping through the JVM execution until I understand<br>
the problem.<br>
<br>
The "logic" of javaPushStackFrames() (my code) is trying to elide noisy<br>
frames. Here it fails to elide frames in your example, as the entry<br>
point is in Primitive.java not Primitives.java, so this code should be<br>
changed. I would go with a simpler implementation of<br>
javaPushStackFrames() that doesn't try to elide frames, and place such a<br>
mechanism on actually viewing the stack. Perhaps we can get SLIME to<br>
"collapse" the Java portion of the backtrace (ala "the inspector") into<br>
a single statement of the source location that the Lisp computation<br>
enter the JVM error condition?<br>
<br>
Hopefully that provides some background for a proposal for a less noisy<br>
backtrace for your purposes to be possible. Since I often get bug<br>
reports consisting of little or more reproduction instructions than: "I<br>
have a problem with ABCL: it gave me this error." and a paste of the<br>
stack trace, it has been useful to have more information present than not.<br>
<br>
One could certainly somehow collapse frames 0-3 somehow into a single<br>
frame that represents the debugger invocation.<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
<br>
<br>
<br>
<br>
><br>
> Thanks,<br>
> Alan<br>
><br>
><br>
> The value CL-UTILS::FORMS is not of type LIST.<br>
> [Condition of type TYPE-ERROR]<br>
><br>
> Restarts:<br>
> 0: [RETRY] Retry compiling #<ASDF/LISP-ACTION:CL-SOURCE-<wbr>FILE "jnil"<br>
> "cl-utils">.<br>
> 1: [ACCEPT] Continue, treating compiling #<ASDF/LISP-ACTION:CL-SOURCE-<wbr>FILE<br>
> "jnil" "cl-utils"> as having been successful.<br>
> 2: [RETRY] Retry ASDF operation.<br>
> 3: [CLEAR-CONFIGURATION-AND-<wbr>RETRY] Retry ASDF operation after resetting<br>
> the configuration.<br>
> 4: [ABORT] Abort compilation.<br>
> 5: [*ABORT] Return to SLIME's top level.<br>
> --more--<br>
><br>
> Backtrace:<br>
> 0: (#<LOCAL-FUNCTION IN MAKE-INVOKE-DEBUGGER-HOOK {5108C7A9}><br>
> #<TYPE-ERROR {D3CDE50}> #<LOCAL-FUNCTION IN MAKE-INVOKE-DEBUGGER-HOOK<br>
> {5108C7A9}>)<br>
> 1: (APPLY #<LOCAL-FUNCTION IN MAKE-INVOKE-DEBUGGER-HOOK {5108C7A9}><br>
> (#<TYPE-ERROR {D3CDE50}> #<LOCAL-FUNCTION IN MAKE-INVOKE-DEBUGGER-HOOK<br>
> {5108C7A9}>))<br>
> 2: (SYSTEM::RUN-HOOK SYSTEM::*INVOKE-DEBUGGER-HOOK* #<TYPE-ERROR<br>
> {D3CDE50}> #<LOCAL-FUNCTION IN MAKE-INVOKE-DEBUGGER-HOOK {5108C7A9}>)<br>
> 3: (INVOKE-DEBUGGER #<TYPE-ERROR {D3CDE50}>)<br>
> 4: org.armedbear.lisp.Lisp.error(<wbr>Lisp.java:382)<br>
> 5: org.armedbear.lisp.Lisp.type_<wbr>error(Lisp.java:435)<br>
> 6: org.armedbear.lisp.LispObject.<wbr>car(LispObject.java:165)<br>
> 7: org.armedbear.lisp.<wbr>precompiler_51.execute(<wbr>precompiler.lisp:381)<br>
> 8: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 9: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 10: org.armedbear.lisp.<wbr>precompiler_48.execute(<wbr>precompiler.lisp:350)<br>
> 11: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 12: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 13: org.armedbear.lisp.<wbr>precompiler_51.execute(<wbr>precompiler.lisp:381)<br>
> 14: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 15: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 16: org.armedbear.lisp.<wbr>precompiler_48.execute(<wbr>precompiler.lisp:350)<br>
> 17: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 18: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 19: org.armedbear.lisp.<wbr>precompiler_51.execute(<wbr>precompiler.lisp:381)<br>
> 20: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 21: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 22: org.armedbear.lisp.<wbr>precompiler_48.execute(<wbr>precompiler.lisp:350)<br>
> 23: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 24: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 25: org.armedbear.lisp.<wbr>precompiler_51.execute(<wbr>precompiler.lisp:381)<br>
> 26: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 27: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 28: org.armedbear.lisp.<wbr>precompiler_48.execute(<wbr>precompiler.lisp:350)<br>
> 29: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 30: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 31: org.armedbear.lisp.<wbr>precompiler_51.execute(<wbr>precompiler.lisp:381)<br>
> 32: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 33: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 34: org.armedbear.lisp.<wbr>precompiler_48.execute(<wbr>precompiler.lisp:350)<br>
> 35: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 36: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 37: org.armedbear.lisp.<wbr>precompiler_73.execute(<wbr>precompiler.lisp:643)<br>
> 38: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 39: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 40: org.armedbear.lisp.<wbr>precompiler_48.execute(<wbr>precompiler.lisp:350)<br>
> 41: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 42: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 43: org.armedbear.lisp.<wbr>precompiler_105.execute(<wbr>precompiler.lisp:988)<br>
> 44: org.armedbear.lisp.<wbr>CompiledClosure.execute(<wbr>CompiledClosure.java:121)<br>
> 45: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:826)<br>
> 46: org.armedbear.lisp.compiler_<wbr>pass2_362.execute(compiler-<wbr>pass2.lisp:7380)<br>
> 47: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:867)<br>
> 48: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:918)<br>
> 49: org.armedbear.lisp.compile_<wbr>file_19.execute(compile-file.<wbr>lisp:175)<br>
> 50: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:814)<br>
> 51: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:832)<br>
> 52: org.armedbear.lisp.compile_<wbr>file_51.execute(compile-file.<wbr>lisp:655)<br>
> 53: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:826)<br>
> 54: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:851)<br>
> 55: org.armedbear.lisp.compile_<wbr>file_59.execute(compile-file.<wbr>lisp:780)<br>
> 56: org.armedbear.lisp.compiler_<wbr>pass2_370.execute(compiler-<wbr>pass2.lisp:7450)<br>
> 57: org.armedbear.lisp.<wbr>CompiledClosure.execute(<wbr>CompiledClosure.java:98)<br>
> 58: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:803)<br>
> 59: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:814)<br>
> 60: org.armedbear.lisp.compile_<wbr>file_57.execute(compile-file.<wbr>lisp:780)<br>
> 61: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:914)<br>
> 62: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:986)<br>
> 63: org.armedbear.lisp.compile_<wbr>file_68.execute(compile-file.<wbr>lisp:962)<br>
> 64: org.armedbear.lisp.<wbr>CompiledClosure.execute(<wbr>CompiledClosure.java:150)<br>
> 65: org.armedbear.lisp.Symbol.<wbr>execute(Symbol.java:852)<br>
> 66: org.armedbear.lisp.LispThread.<wbr>execute(LispThread.java:894)<br>
> 67: org.armedbear.lisp.Lisp.<wbr>funcall(Lisp.java:180)<br>
> 68: org.armedbear.lisp.Primitives$<wbr>pf_apply.execute(Primitives.<wbr>java:2845)<br>
> 69: (PRECOMPILER::PRECOMPILE-<wbr>FUNCTION-CALL (CL-UTILS::KEY .<br>
> CL-UTILS::FORMS))<br>
> 70: (PRECOMPILER::PRECOMPILE1 (CL-UTILS::KEY . CL-UTILS::FORMS))<br>
> 71: (PRECOMPILER::PRECOMPILE-<wbr>FUNCTION-CALL (CL-UTILS::LOOP CL-UTILS::FOR<br>
> (CL-UTILS::KEY . CL-UTILS::FORMS) CL-UTILS::IN CL-UTILS::CLAUSES<br>
> CL-UTILS::DO ...))<br>
> 72: (PRECOMPILER::PRECOMPILE1 (CL-UTILS::LOOP CL-UTILS::FOR (CL-UTILS::KEY<br>
> . CL-UTILS::FORMS) CL-UTILS::IN CL-UTILS::CLAUSES CL-UTILS::DO ...))<br>
> 73: (PRECOMPILER::PRECOMPILE-<wbr>FUNCTION-CALL (CL-UTILS::LET<br>
> ((CL-UTILS::CLAUSE-COLLECTION (CL-UTILS::LIST))) ..))<br>
> 74: (PRECOMPILER::PRECOMPILE1 (CL-UTILS::LET ((CL-UTILS::CLAUSE-COLLECTION<br>
> (CL-UTILS::LIST))) ..))<br>
> 75: (PRECOMPILER::PRECOMPILE-<wbr>FUNCTION-CALL (CL-UTILS::WITH-GENSYMS<br>
> (CL-UTILS::TEST) ..))<br>
> 76: (PRECOMPILER::PRECOMPILE1 (CL-UTILS::WITH-GENSYMS (CL-UTILS::TEST) ..))<br>
> 77: (PRECOMPILER::PRECOMPILE-<wbr>FUNCTION-CALL (CL-UTILS::DEFMACRO<br>
> CL-UTILS::CASE* (CL-UTILS::KEYFORM CL-UTILS::&REST CL-UTILS::CLAUSES) ..))<br>
> 78: (PRECOMPILER::PRECOMPILE1 (CL-UTILS::DEFMACRO CL-UTILS::CASE*<br>
> (CL-UTILS::KEYFORM CL-UTILS::&REST CL-UTILS::CLAUSES) ..))<br>
> 79: (PRECOMPILER::PRECOMPILE-<wbr>LAMBDA (LAMBDA NIL ..))<br>
> 80: (PRECOMPILER::PRECOMPILE1 (LAMBDA NIL (CL-UTILS::DEFMACRO<br>
> CL-UTILS::CASE* (CL-UTILS::KEYFORM CL-UTILS::&REST CL-UTILS::CLAUSES)<br>
> (CL-UTILS::WITH-GENSYMS (CL-UTILS::TEST) (CL-UTILS::LET # # #)))))<br>
> 81: (JVM:COMPILE-DEFUN NIL (LAMBDA NIL (CL-UTILS::DEFMACRO CL-UTILS::CASE*<br>
> (CL-UTILS::KEYFORM CL-UTILS::&REST CL-UTILS::CLAUSES)<br>
> (CL-UTILS::WITH-GENSYMS (CL-UTILS::TEST) (CL-UTILS::LET # # #)))) NIL<br>
> #P"/U..<br>
> 82: (SYSTEM::CONVERT-TOPLEVEL-FORM (CL-UTILS::DEFMACRO CL-UTILS::CASE*<br>
> (CL-UTILS::KEYFORM CL-UTILS::&REST CL-UTILS::CLAUSES) ..) NIL)<br>
> 83: (SYSTEM::PROCESS-TOPLEVEL-FORM (CL-UTILS::DEFMACRO CL-UTILS::CASE*<br>
> (CL-UTILS::KEYFORM CL-UTILS::&REST CL-UTILS::CLAUSES) ..) #<FILE-STREAM<br>
> {1773B7E}> NIL)<br>
> 84: (JVM::%WITH-COMPILATION-UNIT #<LOCAL-FUNCTION IN COMPILE-FROM-STREAM<br>
> {1FEBE62E}>)<br>
> 85: (SYSTEM::COMPILE-FROM-STREAM #<FILE-STREAM {744E75DD}><br>
> #P"/Users/lori/.cache/common-<wbr>lisp/abcl-1.5.0-dev-fasl43-<wbr>macosx-x64/Volumes/upstairs/<wbr>repos/jnil/lisp/jnil/cl-utils-<wbr>tmpUYPFRO0B.abcl"<br>
> #P"/Users/lor..<br>
> 86: (COMPILE-FILE #P"/Volumes/upstairs/repos/<wbr>jnil/lisp/jnil/cl-utils.lisp"<br>
> :OUTPUT-FILE<br>
> #P"/Users/lori/.cache/common-<wbr>lisp/abcl-1.5.0-dev-fasl43-<wbr>macosx-x64/Volumes/upstairs/<wbr>repos/jnil/lisp/jnil/cl-utils-<wbr>tm..<br>
> 87: (APPLY COMPILE-FILE<br>
> #P"/Volumes/upstairs/repos/<wbr>jnil/lisp/jnil/cl-utils.lisp" :OUTPUT-FILE<br>
> #P"/Users/lori/.cache/common-<wbr>lisp/abcl-1.5.0-dev-fasl43-<wbr>macosx-x64/Volumes/upstairs/<wbr>repos/jnil/lisp/jnil/cl-ut..<br>
><br>
><br>
><br>
><br>
><br>
> private static final void pushJavaStackFrames()<br>
> {<br>
> final LispThread thread = LispThread.currentThread();<br>
> final StackTraceElement[] frames = thread.getJavaStackTrace();<br>
><br>
> // frames[0] java.lang.Thread.getStackTrace<br>
> // frames[1] org.armedbear.lisp.LispThread.<wbr>getJavaStackTrace<br>
> // frames[2] org.armedbear.lisp.Lisp.<wbr>pushJavaStackFrames<br>
><br>
> if (frames.length > 5<br>
> && frames[3].getClassName().<wbr>equals("org.armedbear.lisp.<wbr>Lisp")<br>
> && frames[3].getMethodName().<wbr>equals("error")<br>
> && frames[4].getClassName().<wbr>startsWith("org.armedbear.<wbr>lisp.Lisp")<br>
> && frames[4].getMethodName().<wbr>equals("eval")) {<br>
> // Error condition arising from within Lisp.eval(), so no<br>
> // Java stack frames should be visible to the consumer of the<br>
> stack abstraction<br>
> return;<br>
> }<br>
> // Search for last Primitive in the StackTrace; that was the<br>
> // last entry point from Lisp.<br>
> int last = frames.length - 1;<br>
> for (int i = 0; i<= last; i++) {<br>
> if<br>
> (frames[i].getClassName().<wbr>startsWith("org.armedbear.<wbr>lisp.Primitive"))<br>
> last = i;<br>
> }<br>
> // Do not include the first three frames which, as noted above,<br>
> constitute<br>
> // the invocation of this method.<br>
> while (last > 2) {<br>
> thread.pushStackFrame(new JavaStackFrame(frames[last]));<br>
> last--;<br>
> }<br>
> }<br>
><br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">--<br>
"A screaming comes across the sky. It has happened before, but there<br>
is nothing to compare to it now."<br>
<br>
</font></span></blockquote></div><br></div></div></div>