Hello,
As you well know, SLIME's debugger, when invoked, will inevitably add some frames to the current stack, which SWANK attempts to hide. On Allegro, when signalling an error from the REPL, those extra frames look something like this:
0: ((FLET (:TOP-LEVEL-FORM "swank-allegro.lisp" 4123) SWANK- BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT) #<Function (:INTERNAL SWANK::DEBUG-IN-EMACS 0)>) 1: (SWANK-BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT #<Function (:INTERNAL SWANK::DEBUG-IN-EMACS 0)>) 2: (SWANK::DEBUG-IN-EMACS #<SIMPLE-ERROR @ #x218114d2>) 3: (SWANK:INVOKE-SLIME-DEBUGGER #<SIMPLE-ERROR @ #x218114d2>) 4: ((:INTERNAL SWANK:SWANK-DEBUGGER-HOOK 1)) 5: ((:INTERNAL (:TOP-LEVEL-FORM "swank-backend.lisp" 32198) 0) #<Function SWANK-DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:SWANK- DEBUGGER-HOOK 1) @ #x218115f2>) 6: (SWANK-BACKEND:CALL-WITH-DEBUGGER-HOOK #<Function SWANK- DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:SWANK-DEBUGGER-HOOK 1) @ #x218115f2>) 7: (SWANK:SWANK-DEBUGGER-HOOK #<SIMPLE-ERROR @ #x218114d2> #<Function SWANK-DEBUGGER-HOOK>) 8: (ERROR "foo")
In this case, FIND-TOPLEVEL in swank-allegro.lisp successfully figures out that the first 8 frames are to be hidden.
However, if the error comes from some other thread -- this can be reproduced via (mp:process-run-function nil (lambda () (error "foo"))) for example -- there will a couple of extra frames:
0: ((FLET (:TOP-LEVEL-FORM "swank-allegro.lisp" 4123) SWANK- BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT) #<Function (:INTERNAL SWANK::DEBUG-IN-EMACS 0)>) 1: (SWANK-BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT #<Function (:INTERNAL SWANK::DEBUG-IN-EMACS 0)>) 2: (SWANK::DEBUG-IN-EMACS #<SIMPLE-ERROR @ #x21552f92>) 3: ((:INTERNAL SWANK:INVOKE-SLIME-DEBUGGER 0)) 4: ((:INTERNAL (:TOP-LEVEL-FORM "swank-backend.lisp" 32198) 0) #<Function SWANK-DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:INVOKE-SLIME-DEBUGGER 0) @ #x215530e2>) 5: (SWANK-BACKEND:CALL-WITH-DEBUGGER-HOOK #<Function SWANK- DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:INVOKE-SLIME-DEBUGGER 0) @ #x215530e2>) 6: ((:INTERNAL SWANK:INVOKE-SLIME-DEBUGGER 3)) 7: (SWANK::CALL-WITH-BINDINGS ..) 8: (SWANK:INVOKE-SLIME-DEBUGGER #<SIMPLE-ERROR @ #x21552f92>) 9: ((:INTERNAL SWANK:SWANK-DEBUGGER-HOOK 1)) 10: ((:INTERNAL (:TOP-LEVEL-FORM "swank-backend.lisp" 32198) 0) #<Function SWANK-DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:SWANK- DEBUGGER-HOOK 1) @ #x2155309a>) 11: (SWANK-BACKEND:CALL-WITH-DEBUGGER-HOOK #<Function SWANK- DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:SWANK-DEBUGGER-HOOK 1) @ #x2155309a>) 12: (SWANK:SWANK-DEBUGGER-HOOK #<SIMPLE-ERROR @ #x21552f92> #<Function SWANK-DEBUGGER-HOOK>) 13: (ERROR "foo")
Because FIND-TOPLEVEL currently only looks at the first eleven frames, it will fail to find frame #12 in the stacktrace above. Consequently, the extra debugger frames won't be hidden.
The attached patch fixes this by looking a bit further (30 frames) taking care not to fail on small stacks.
I considered the idea of not hard-coding an arbitrary limit, but in the end went with the more conservative fix since walking through a very large stack takes a while. (However, it seems unlikely that FIND-TOPFRAME would ever be called in a context where SWANK-DEBUGGER-HOOK is not on the stack, modulo protocol changes that would break the whole scheme anyway.)
Cheers,
Luís Oliveira luismbo@gmail.com writes:
Hello,
As you well know, SLIME's debugger, when invoked, will inevitably add some frames to the current stack, which SWANK attempts to hide. On Allegro, when signalling an error from the REPL, those extra frames look something like this:
0: ((FLET (:TOP-LEVEL-FORM "swank-allegro.lisp" 4123) SWANK- BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT) #<Function (:INTERNAL SWANK::DEBUG-IN-EMACS 0)>) 1: (SWANK-BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT #<Function (:INTERNAL SWANK::DEBUG-IN-EMACS 0)>) 2: (SWANK::DEBUG-IN-EMACS #<SIMPLE-ERROR @ #x218114d2>) 3: (SWANK:INVOKE-SLIME-DEBUGGER #<SIMPLE-ERROR @ #x218114d2>) 4: ((:INTERNAL SWANK:SWANK-DEBUGGER-HOOK 1)) 5: ((:INTERNAL (:TOP-LEVEL-FORM "swank-backend.lisp" 32198) 0) #<Function SWANK-DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:SWANK- DEBUGGER-HOOK 1) @ #x218115f2>) 6: (SWANK-BACKEND:CALL-WITH-DEBUGGER-HOOK #<Function SWANK- DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:SWANK-DEBUGGER-HOOK 1) @ #x218115f2>) 7: (SWANK:SWANK-DEBUGGER-HOOK #<SIMPLE-ERROR @ #x218114d2> #<Function SWANK-DEBUGGER-HOOK>) 8: (ERROR "foo")
In this case, FIND-TOPLEVEL in swank-allegro.lisp successfully figures out that the first 8 frames are to be hidden.
However, if the error comes from some other thread -- this can be reproduced via (mp:process-run-function nil (lambda () (error "foo"))) for example -- there will a couple of extra frames:
0: ((FLET (:TOP-LEVEL-FORM "swank-allegro.lisp" 4123) SWANK- BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT) #<Function (:INTERNAL SWANK::DEBUG-IN-EMACS 0)>) 1: (SWANK-BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT #<Function (:INTERNAL SWANK::DEBUG-IN-EMACS 0)>) 2: (SWANK::DEBUG-IN-EMACS #<SIMPLE-ERROR @ #x21552f92>) 3: ((:INTERNAL SWANK:INVOKE-SLIME-DEBUGGER 0)) 4: ((:INTERNAL (:TOP-LEVEL-FORM "swank-backend.lisp" 32198) 0) #<Function SWANK-DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:INVOKE-SLIME-DEBUGGER 0) @ #x215530e2>) 5: (SWANK-BACKEND:CALL-WITH-DEBUGGER-HOOK #<Function SWANK- DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:INVOKE-SLIME-DEBUGGER 0) @ #x215530e2>) 6: ((:INTERNAL SWANK:INVOKE-SLIME-DEBUGGER 3)) 7: (SWANK::CALL-WITH-BINDINGS ..) 8: (SWANK:INVOKE-SLIME-DEBUGGER #<SIMPLE-ERROR @ #x21552f92>) 9: ((:INTERNAL SWANK:SWANK-DEBUGGER-HOOK 1)) 10: ((:INTERNAL (:TOP-LEVEL-FORM "swank-backend.lisp" 32198) 0) #<Function SWANK-DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:SWANK- DEBUGGER-HOOK 1) @ #x2155309a>) 11: (SWANK-BACKEND:CALL-WITH-DEBUGGER-HOOK #<Function SWANK- DEBUGGER-HOOK> #<Closure (:INTERNAL SWANK:SWANK-DEBUGGER-HOOK 1) @ #x2155309a>) 12: (SWANK:SWANK-DEBUGGER-HOOK #<SIMPLE-ERROR @ #x21552f92> #<Function SWANK-DEBUGGER-HOOK>) 13: (ERROR "foo")
Because FIND-TOPLEVEL currently only looks at the first eleven frames, it will fail to find frame #12 in the stacktrace above. Consequently, the extra debugger frames won't be hidden.
The attached patch fixes this by looking a bit further (30 frames) taking care not to fail on small stacks.
I considered the idea of not hard-coding an arbitrary limit, but in the end went with the more conservative fix since walking through a very large stack takes a while. (However, it seems unlikely that FIND-TOPFRAME would ever be called in a context where SWANK-DEBUGGER-HOOK is not on the stack, modulo protocol changes that would break the whole scheme anyway.)
Applied, thanks.