[slime-devel] [PATCH] hiding swank frames from debugger backtrace on Allegro

Luís Oliveira luismbo at gmail.com
Thu Mar 14 11:31:08 UTC 2013


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
http://r42.eu/~luis

-------------- next part --------------
diff --git a/ChangeLog b/ChangeLog
index 70f869c..393bb85 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2013-03-14  Luís Oliveira  <loliveira at common-lisp.net>
+
+	Hide SWANK debugger frames on Allegro also when the error is
+	signalled within threads different from the SLIME REPL's.
+	E.g. (mp:process-run-function nil (lambda () (error "foo"))).
+
+	* swank-allegro.lisp (find-topframe): look deeper than 11
+	frames. Still looking no deeper than 30 frames in the unlikely
+	event that this function is invoked out of context with a very
+	large stack.
+
 2013-03-12  Helmut Eller  <heller at common-lisp.net>
 
 	* slime.el (slime-read-interactive-args): Use read-shell-command
diff --git a/swank-allegro.lisp b/swank-allegro.lisp
index ef286c0..cb6ffe0 100644
--- a/swank-allegro.lisp
+++ b/swank-allegro.lisp
@@ -169,11 +169,11 @@
                               (find-package :swank)))
         (top-frame (excl::int-newest-frame (excl::current-thread))))
     (loop for frame = top-frame then (next-frame frame)
-          for name  = (debugger:frame-name frame)
           for i from 0
-          when (eq name magic-symbol)
+          while (and frame (< i 30))
+          when (eq (debugger:frame-name frame) magic-symbol)
             return (next-frame frame)
-          until (= i 10) finally (return top-frame))))
+          finally (return top-frame))))
 
 (defun next-frame (frame)
   (let ((next (excl::int-next-older-frame frame)))



More information about the slime-devel mailing list