chicken-users
[Top][All Lists]
Advanced

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

Re: [Chicken-users] Threads and dynamic-wind still problematic


From: Jim Ursetto
Subject: Re: [Chicken-users] Threads and dynamic-wind still problematic
Date: Tue, 10 Mar 2009 16:43:00 -0500

On Mon, Mar 2, 2009 at 3:48 PM, Peter Bex <address@hidden> wrote:
> However, it turns out that an exception thrown in a thread simply
> terminates the thread instead of unwinding the stack.  The same does not
> happen in the primordial thread:

> $ csi
> #;2> (dynamic-wind (lambda () (print "BEFORE")) (lambda () (error "die!")) 
> (lambda () (print "AFTER")))
> BEFORE
> Error: die!
> AFTER

Hi Peter.  You might disagree with the rationale, but the behavior is
in fact consistent--your example only happens to work at the REPL.
Try compiling that or calling it with `csi -eval`, and you will see
the after thunk is not invoked.  When you are not at a REPL, the
default error handler will immediately terminate the program upon
error, or break into a repl if you've enabled that option; the after
thunks are not invoked.

When you *are* at a REPL, the default error handler is overridden to
print an error message without terminating, and then the reset handler
is called.  The magic comes in when, before evaluating your
expression, the REPL captures the current continuation and overrides
the reset handler to invoke it.  When an error occurs, that
continuation is invoked to return to the REPL, *and* by doing so, your
dynamic-wind after thunks are invoked.

Note that this is exactly what Marc Feeley prescribed: "If the
programmer knows how to recover from an exception, then he can capture
the continuation early on, and install an exception handler which
invokes the continuation.  When the continuation is invoked the after
thunks will execute."  It just happens that at a REPL, exception
recovery corresponds to "continue with the REPL".

Here is a little program which demonstrates in essence what the repl
is doing.  Compile with `csc x.scm`.

(define (simulate-repl thunk)
  (let ((eh (##sys#error-handler))
        (rh (##sys#reset-handler)))
    (dynamic-wind
        (lambda () (##sys#error-handler
               (lambda (msg . args) (apply print "Error: " msg args))))
        (lambda ()
          (let ((k (call/cc (lambda (c)
                              (##sys#reset-handler
                               (lambda () (c #f)))))))
            (if k (thunk))))
        (lambda ()
          (##sys#error-handler eh)
          (##sys#reset-handler rh)))))

(define (test)
  (dynamic-wind
      (lambda () (print "BEFORE"))
      (lambda () (error "die!"))
      (lambda () (print "AFTER"))))

(simulate-repl test)
(test)
(test) ; not reached

#| Output
BEFORE
Error: die!
AFTER
BEFORE
Error: die!
|#




reply via email to

[Prev in Thread] Current Thread [Next in Thread]