Subject: [clisp-list] auto debugging

From: Pascal J.Bourguignon <[email-masked]>
Date: Wed Sep 10 13:39:16 2003

In situations  where there's  no interactive channel  to a  clisp, how
could I direct the debugger to issue a backtrace automatically?

I first tried to set a *debugger-hook*, but then I've no access to the
frames to be backtracked:

[2]> (setq *debugger-hook* (lambda (condition last-hook)
                          (format t "~&ERROR: ~A" condition)
                          (let ((system::*debug-mode* 1)
                                (system::*debug-frame* (SYSTEM::THE-FRAME)))
                            (SYSTEM::DEBUG-BACKTRACE))))
#<CLOSURE :LAMBDA (CONDITION LAST-HOOK) (FORMAT T "~&ERROR: ~A" CONDITION)
  (LET ((SYSTEM::*DEBUG-MODE* 1) (SYSTEM::*DEBUG-FRAME* (SYSTEM::THE-FRAME)))
   (SYSTEM::DEBUG-BACKTRACE))>
[9]> (/ 1 0)
ERROR: division by zero
*** - SYSTEM::FRAME-UP-1: NIL is not a stack pointer
1. Break [10]> 

Then I tried something like:

[2]> (let ((*debug-io* 
             (make-two-way-stream 
                (make-string-input-stream (format nil ":bt~%(ext:quit)~%")) 
                *standard-output*))) 
       (let ((a 0)) (format t "~D~%" (/ 1 a))))
*** - division by zero
1. Break [9]> 
:BT
1. Break [9]> 

but while it's echoing :BT it does not seem to exectute it.

I even tried with more redirections:

(let* ((*standard-input* 
        (make-string-input-stream (format nil ":bt~%(ext:quit)~%"))) 
       (*debug-io* (make-two-way-stream *standard-input* *standard-output*))
       (*terminal-io* *debug-io*) 
       (*query-io* *debug-io*)) 
 (let ((a 0)) (format t "~D~%" (/ 1 a))))

but this only hangs clisp.

I'd like it  to dump a backtrace automatically  in addition to issuing
the error message.

-- 
__Pascal_Bourguignon__
http://www.informatimago.com/
Do not adjust your mind, there is a fault in reality.

---

From: Sam Steingold <[email-masked]>
Date: Wed Sep 10 14:46:29 2003

>* Pascal J.Bourguignon <[email-masked]> [2003-09-10 22:37:40 +0200]:
>

almost.  see `break-loop' in src/reploop.lisp:

[1]> (setq *debugger-hook*
      (lambda (condition last-hook)
        (format t "~&ERROR: ~A" condition)
        (let* ((sys::*frame-limit1* (sys::frame-limit1 13))
               (sys::*frame-limit2* (sys::frame-limit2))
               (sys::*debug-mode* 1)
               (sys::*debug-frame*
                (sys::frame-down-1 (sys::frame-up-1 sys::*frame-limit1*
                                                    sys::*debug-mode*)
                                   sys::*debug-mode*)))
          (system::debug-backtrace))))
#<CLOSURE :LAMBDA (CONDITION LAST-HOOK) (FORMAT T "~&ERROR: ~A" CONDITION)
  (LET*
   ((SYSTEM::*FRAME-LIMIT1* (SYSTEM::FRAME-LIMIT1 13))
    (SYSTEM::*FRAME-LIMIT2* (SYSTEM::FRAME-LIMIT2)) (SYSTEM::*DEBUG-MODE* 1)
    (SYSTEM::*DEBUG-FRAME*
     (SYSTEM::FRAME-DOWN-1
      (SYSTEM::FRAME-UP-1 SYSTEM::*FRAME-LIMIT1* SYSTEM::*DEBUG-MODE*)
      SYSTEM::*DEBUG-MODE*)))
   (SYSTEM::DEBUG-BACKTRACE))>
[2]> (/ 0 1)
0
[3]> (/ 1 0)
ERROR: division by zero
[1]> #<SYSTEM-FUNCTION SHOW-STACK>
[2]> #<COMPILED-CLOSURE SYSTEM::DEBUG-BACKTRACE>
[3]> #<SPECIAL-OPERATOR LET*>
[4]>
#<CLOSURE :LAMBDA (CONDITION LAST-HOOK) (FORMAT T "~&ERROR: ~A" CONDITION)
  (LET*
   ((SYSTEM::*FRAME-LIMIT1* (SYSTEM::FRAME-LIMIT1 13))
    (SYSTEM::*FRAME-LIMIT2* (SYSTEM::FRAME-LIMIT2)) (SYSTEM::*DEBUG-MODE* 1)
    (SYSTEM::*DEBUG-FRAME*
     (SYSTEM::FRAME-DOWN-1
      (SYSTEM::FRAME-UP-1 SYSTEM::*FRAME-LIMIT1* SYSTEM::*DEBUG-MODE*)
      SYSTEM::*DEBUG-MODE*)))
   (SYSTEM::DEBUG-BACKTRACE))> 2
[5]> #<SYSTEM-FUNCTION INVOKE-DEBUGGER>
- #<SYSTEM::SIMPLE-DIVISION-BY-ZERO #x19ECF54D>
- 0
[6]> #<SYSTEM-FUNCTION /> 1
- 1
EVAL frame for form (/ 1 0)
- #<IO TERMINAL-STREAM>
[7]> #<SYSTEM-FUNCTION SYSTEM::READ-EVAL-PRINT>
- #<IO TERMINAL-STREAM>
Printed 7 frames
[4]>

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Marriage is the sole cause of divorce.

---

From: Pascal J.Bourguignon <[email-masked]>
Date: Wed Sep 10 16:48:49 2003

>           (system::debug-backtrace))))

Thank you,

---

From: Pascal J.Bourguignon <[email-masked]>
Date: Thu Sep 11 17:56:07 2003

>           (system::debug-backtrace))))

I had  to add a catch on  'system::debug, and noted that  it outputs a
"Printed NN frames" to *debug-io*:

(DEFUN BACKTRACE (&OPTIONAL (OUTPUT  *STANDARD-OUTPUT*) (DEBUG *DEBUG-IO*))
  "
DO:     Prints a backtrace to the OUTPUT stream,
        and report the number of printed frames on the DEBUG frame.
NOTE:   To be used in debugger hooks, but can be called from anywhere.
"
  (LET ((*STANDARD-OUTPUT* OUTPUT)
        (*DEBUG-IO*        DEBUG))
    (CATCH 'SYSTEM::DEBUG
              (LET* ((SYS::*FRAME-LIMIT1* (SYS::FRAME-LIMIT1 13))
                     (SYS::*FRAME-LIMIT2* (SYS::FRAME-LIMIT2))
                     (SYS::*DEBUG-MODE* 1)
                     (SYS::*DEBUG-FRAME*
                      (SYS::FRAME-DOWN-1 (SYS::FRAME-UP-1 SYS::*FRAME-LIMIT1*
                                                          SYS::*DEBUG-MODE*)
                                         SYS::*DEBUG-MODE*)))
                (SYSTEM::DEBUG-BACKTRACE))))
  );;BACKTRACE

Thanks again for you help.
-- 
__Pascal_Bourguignon__
http://www.informatimago.com/
Do not adjust your mind, there is a fault in reality.

---

From: Sam Steingold <[email-masked]>
Date: Fri Sep 12 12:59:14 2003

>* Pascal J.Bourguignon <[email-masked]> [2003-09-12 02:54:23 +0200]:
>
> Sam Steingold writes:

note that you can write

(defun backtrace (&optional (*standard-output* *standard-output*)
                  (*debug-io* *debug-io*))
  ...)

instead of

(defun backtrace (&optional (output  *standard-output*) (debug *debug-io*))
  (let ((*standard-output* output)
        (*debug-io*        debug))
     ...))

> Thanks again for you help.
welcome.
-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Small languages require big programs, large languages enable small programs.