Whenever the system dispatches an event, the call to the handler
procedure is wrapped so that full continuation jumps are not allowed
to escape from the dispatch, and escape continuation jumps are
blocked at the dispatch site. The following block procedure
illustrates how the system blocks escape continuation jumps:
(block (lambda () 5)) ; => 5
(let/ec k (block (lambda () (k 10)))) ; => void
(let/ec k ((lambda () (k 10))) 11) ; => 10
(let/ec k (block (lambda () (k 10))) 11) ; => 11
(define (block f)
; calls f, returning (void) if f tries to escape
(let ([done? #f])
(let/ec k
(dynamic-wind
void
(lambda () (begin0 (f) (set! done? #t)))
(lambda () (unless done? (k (void))))))))
Calls to the event dispatch handler are also protected with
block.
This blocking of continuation jumps complicates the interaction
between with-handlers and yield (or the default
event dispatch handler). For example, in evaluating the expression
(with-handlers ([(lambda (x) #t)
(lambda (x) (error "error during yield"))])
(yield))
the "error during yield" handler is never called, even
if a callback procedure invoked by yield raises an
exception. The with-handlers expression installs an exception
handler that tries to jump back to the context of the
with-handlers expression before invoking a handler procedure;
this jump is blocked by the dispatch within yield, so
"error during yield" is never printed. Exceptions during
yield are ``handled'' in the sense that control jumps
out of the event handler, but yield may dispatch
another event rather than escaping or returning.
The following expression demonstrates a more useful way to handle
exceptions within yield:
(let/ec k
(parameterize ([current-exception-handler
(lambda (x)
(error "error during yield")
(k))])
(yield)))
This expression installs an exception handler that prints an error
message before trying to escape. Like the continuation escape
associated with with-handlers, the escape to k never
succeeds. Nevertheless, if an exception is raised by an event
handler during the call to yield, an error message is
printed before control returns to the event dispatcher within
yield.