Next: , Previous: , Up: Programmatic Error Handling   [Contents][Index]


6.27.3.2 Capturing the full error stack

The other interesting information about an error is the full Scheme stack at the point where the error occurred; in other words what innermost expression was being evaluated, what was the expression that called that one, and so on. If you want to write your code so that it captures and can display this information as well, there are a couple important things to understand.

Firstly, the stack at the point of the error needs to be explicitly captured by a make-stack call (or the C equivalent scm_make_stack). The Guile library does not do this “automatically” for you, so you will need to write code with a make-stack or scm_make_stack call yourself. (We emphasise this point because some people are misled by the fact that the Guile interactive REPL code does capture and display the stack automatically. But the Guile interactive REPL is itself a Scheme program20 running on top of the Guile library, and which uses catch and make-stack in the way we are about to describe to capture the stack when an error occurs.)

And secondly, in order to capture the stack effectively at the point where the error occurred, the make-stack call must be made before Guile unwinds the stack back to the location of the prevailing catch expression. This means that the make-stack call must be made within the handler of a with-throw-handler expression, or the optional "pre-unwind" handler of a catch. (For the full story of how these alternatives differ from each other, see Exceptions. The main difference is that catch terminates the error, whereas with-throw-handler only intercepts it temporarily and then allow it to continue propagating up to the next innermost handler.)

So, here are some examples of how to do all this in Scheme and in C. For the purpose of these examples we assume that the captured stack should be stored in a variable, so that it can be displayed or arbitrarily processed later on. In Scheme:

(let ((captured-stack #f))
  (catch #t
         (lambda ()
           ;; Execute the code in which
           ;; you want to catch errors here.
           ...)
         (lambda (key . parameters)
           ;; Put the code which you want
           ;; to handle an error after the
           ;; stack has been unwound here.
           ...)
         (lambda (key . parameters)
           ;; Capture the stack here:
           (set! captured-stack (make-stack #t))))
  ...
  (if captured-stack
      (begin
        ;; Display or process the captured stack.
        ...))
  ...)

And in C:

SCM my_body_proc (void *body_data)
{
  /* Execute the code in which
     you want to catch errors here. */
  ...
}

SCM my_handler_proc (void *handler_data,
                     SCM key,
                     SCM parameters)
{
  /* Put the code which you want
     to handle an error after the
     stack has been unwound here. */
  ...
}

SCM my_preunwind_proc (void *handler_data,
                       SCM key,
                       SCM parameters)
{
  /* Capture the stack here: */
  *(SCM *)handler_data = scm_make_stack (SCM_BOOL_T, SCM_EOL);
}

{
  SCM captured_stack = SCM_BOOL_F;
  ...
  scm_c_catch (SCM_BOOL_T,
               my_body_proc, body_data,
               my_handler_proc, handler_data,
               my_preunwind_proc, &captured_stack);
  ...
  if (captured_stack != SCM_BOOL_F)
  {
    /* Display or process the captured stack. */
    ...
  }
  ...
}

Once you have a captured stack, you can interrogate and display its details in any way that you want, using the stack-… and frame-… API described in Stacks and Frames.

If you want to print out a backtrace in the same format that the Guile REPL does, you can use the display-backtrace procedure to do so. You can also use display-application to display an individual frame in the Guile REPL format.


Footnotes

(20)

In effect, it is the default program which is run when no commands or script file are specified on the Guile command line.


Next: , Previous: , Up: Programmatic Error Handling   [Contents][Index]