[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: debugging stack overflow er



>REGARDING                debugging stack overflow errors
>I have a very mysterious problem that I am having considerable 
>difficulty in debugging, so I thought I'd as the list if anybody has
>seen anything similar or could give me any pointers to how to
>go about debugging it.
>
>I have created a stand-alone application with the following toplevel-loop.  
>
>(defun tabletop-toplevel ()
>  (event-dispatch)
>  (handler-case
>    (progn
>      (eval (get-next-queued-form))
>      (process-app-events))  ;;<- defined by our application.
>    (error () nil)))
>
>It works just fine for maybe 10 or 20 minutes, at which point it bombs
>out with Stack Overflow error while running function X, where X has been at 
>various times POINTERP, FRONT-WINDOWS, CCL::WAIT-NEXT-EVENT-SLEEP-TICKS,
>SLOT-VALUE, FIND-CLASS, GET-NEXT-EVENT.  At this point the application is 
>dead in the water, and the only solution is to reboot.  This happens whether
>or not
>the application has any windows open or whether it is running in the
>foreground
>or the background...

There is a bug in the kernel code that calls your toplevel function.
Every time a toplevel function returns, 4 bytes are lost from the
value stack. I've fixed the kernel, but the easiest way around the
problem is to never return from your toplevel function except by
throwing to toplevel (with the TOPLEVEL function). Throwing to
toplevel does not cause stack to be lost. We've never discovered
the bug because MCL's default toplevel function never returns.

(defmacro with-toplevel-loop (&body body)
  `(loop
     (catch-cancel
       (handler-case
         (restart-case
           (progn ,@body)
           (abort () :report (lambda (stream)
                               (format stream "Return to toplevel.")))
           (abort-break () :report (lambda (stream)
                                     (format stream "Return to toplevel."))))
         (error () nil)))))

(defun tabletop-toplevel ()
  (with-toplevel-loop
    (event-dispatch)
    (eval (get-next-queued-form))
    (process-app-events)))

(defun process-app-events ()
  ; ...
  )

(%set-toplevel #'tabletop-toplevel)
(toplevel)


BTW, the code above, and Laura's code will not catch stack overflow or
out of memory errors. These errors are of type STORAGE-CONDITION.
If you make your handler-case catch errors of type SERIOUS-CONDITION,
you'll get all errors. This may NOT be adviseable, as stack overflow
and out of memory errors tend to repeat.