6.26.3.2 Pre-Unwind Debugging

Sometimes when something goes wrong, what you want is not just a representation of the exceptional situation, but the context that brought about that situation. The example in the previous section passed #:unwind #t to with-exception-handler, indicating that raise-exception should unwind the stack before invoking the exception handler. However if you don’t take this approach and instead let the exception handler be invoked in the context of the raise-exception, you can print a backtrace, launch a recursive debugger, or take other “pre-unwind” actions.

The most basic idea would be to simply print a backtrace:

(define (call-with-backtrace thunk)
  (with-exception-handler
    (lambda (exn)
      (backtrace)
      (raise-exception exn))
    thunk))

Here we use the built-in backtrace procedure to print the backtrace.

Scheme Procedure: backtrace [highlights]
C Function: scm_backtrace_with_highlights (highlights)
C Function: scm_backtrace ()

Display a backtrace of the current stack to the current output port. If highlights is given it should be a list; the elements of this list will be highlighted wherever they appear in the backtrace.

By re-raising the exception, call-with-backtrace doesn’t actually handle the error. We could define a version that instead aborts the computation:

(use-modules (ice-9 control))
(define (call-with-backtrace thunk)
  (let/ec cancel
    (with-exception-handler
      (lambda (exn)
        (backtrace)
        (cancel #f))
      thunk)))

In this second example, we use an escape continuation to abort the computation after printing the backtrace, returning #f instead.

It could be that you want to only print a limited backtrace. In that case, use start-stack:

(use-modules (ice-9 control))
(define (call-with-backtrace thunk)
  (let/ec cancel
    (start-stack 'stack-with-backtrace
      (with-exception-handler
        (lambda (exn)
          (backtrace)
          (cancel #f))
        thunk))))

There are also more powerful, programmatic ways to walk the stack using make-stack and friends; see the API described in Stacks and Frames.