29.  Error and Exception Handling  

error-handler

This variable is defined in the global environment. When an error occurs or when the procedure error is invoked and the variable error-handler is bound to a compound procedure (the error handler), the interpreter invokes this procedure. The error handler is called with an object (either the first argument that has been passed to error or a symbol identifying the primitive procedure that has caused the error), and an error message consisting of a format string and a list of objects suitable to be passed to format.

Typically, a user-defined error handler prints the error message and then calls a control point that has been created outside the error handler. If the error handler terminates normally or if error-handler is not bound to a procedure, the error message is printed in a default way, and then a reset is performed.

interrupt-handler

This variable is defined in the global environment. When an interrupt occurs (typically as a result of typing the interrupt character on the keyboard), and the variable interrupt-handler is bound to a procedure (the interrupt handler), this procedure is called with no arguments. If interrupt-handler is not bound to a procedure or if the procedure terminates normally, a message is printed, and a reset is performed.
Examples:

(set! interrupt-handler
  (lambda ()
    (newline)
    (backtrace)
    (reset)))

(disable-interrupts)
(enable-interrupts)

disable-interrupts causes signals to be blocked from delivery to the interpreter; enable-interrupts enables delivery of signals. These functions control delivery of keyboard-generated interrupt signals (see interrupt-handler above) as well as additional signals used by extensions (such as the alarm signal). The interpreter automatically blocks delivery of signals during critical operations, such as garbage collection. Signals are enabled on startup after initialization has completed.

A call to enable-interrupts immediately delivers signals that have been generated while signals were disabled, but blocked signals are not queued. On platforms that support neither POSIX-style nor BSD-style reliable signals, disable-interrupts causes signals to be ignored (as opposed to blocking them until the next call to enable-interrupts).

Calls to disable-interrupts and enable-interrupts can be nested. The functions maintain a count indicating the number of calls to enable-interrupts that it takes to return from a nested disable-interrupts invocation to the topmost level (i.e. to actually enable delivery of signals again). Both functions return this nesting level as an integer.

Example: the following loop ensures that delivery of signals is enabled, regardless of the current nesting depth of disable-interrupts calls:

(let loop ((intr-level (enable-interrupts)))
     (if (positive? intr-level)
         (loop (enable-interrupts))))

dynamic-wind can be used to write a macro with-interrupts-disabled to protect a critical section of code from being interrupted by a signal:

(define-macro (with-interrupts-disabled . body)
  `(dynamic-wind
     (lambda () (disable-interrupts))
     (lambda () ,@body)
     (lambda () (enable-interrupts))))

(error obj string obj ...)

Signals an error. The arguments of error are passed to the error-handler.
Examples:

(define (foo sym)
  (if (not (symbol? sym))
      (error 'foo "argument not a symbol: ~s" sym))
  ...

top-level-control-point
(reset)

reset performs a reset by calling the control point to which the variable top-level-control-point is bound in the global environment. The control point is called with the argument #t. If top-level-control-point is not bound to a control point, or does not exist at all, an error message is printed and the interpreter is terminated.
Examples:

(if (call-with-current-continuation
      (lambda (x)
        (fluid-let ((top-level-control-point x))
          do something
          #f)))
    (print "Got a reset!"))

(exit)
(exit n)

Terminates the interpreter. The optional argument n indicates the exit code; it defaults to zero.


Markup created by unroff 1.0,    September 24, 1996,    net@informatik.uni-bremen.de