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

Issue: UNWIND-PROTECT-CLEANUP-NON-LOCAL-EXIT (Version 4)



re: re: But the very fact that you can run an arbitrary computation implies 
    that you can effectively block a THROW.  For example, I can rewrite the 
    loop shown above as:
	    (labels ((again () (unwind-protect
				    (Run-application-evaluator)
				    (again))))
	      (again))

No, this isn't true.  If you interrupt out of AGAIN and "abort" to toplevel, 
the the barrier is broken.  The part of my emmendation to the proposal that 
makes this clear is:
    ". . . that cleanup form code will:
        (1) abort it's own local processing 
     . . ."
As a previous example on this topic showed, unless an implementation just 
happened to have an "interrupt exposed" critical section, it would be 
possible that every attempt to interupt the computation and "abort" to
a higher level would be blocked and cause re-entry into the cleanup
form again.

As someone has said previously, this proposal isn't about proscriptions 
against writing looping code -- e.g., (prog () A (go A)) -- but about the
dynamic scoping relations between THROW and UNWIND-PROTECT cleanups.  [Well,
if they didn't say exactly that, they should have!]


re: Another point: what good is signalling an error?  It will give handlers a
    chance to run, but is the error allowed to break out without invoking the
    cleanup forms anyway?

The main reason for signalling an error is to help the luser find a possibly
very obscure error that isn't syntatically visible.  The presentations of 
sample losing code have all been lexically in the same scope; but the error
is one of poor intermixture of dynamic components.

But back to your point: "... but is the error allowed to break out without 
invoking the cleanup forms anyway?".  Yes, most certainly.  This suggests
an implementation technique, which I would have described in more detail
had there been time (and space!).  That is, an "unwind-protect frame,
on a stack" is converted into a "cleanup-form frame" during the execution
of its cleanup forms; if that execution completes normally, then the
"cleanup-form frame" is simply popped off the stack, and the next unwind-
protect frame is found and "serviced"; but an attempt to throw through
that "cleanup-form frame" [a non-local exit, in the original terminology
of this proposal] will either (1) simply flush the frame, thereby effecting
a "break out" of the "cleanup-form frame", because the throw target is merely 
extending a previously "committed" throw, or (2) signal an error because the 
throw target is scoped erroneously as described in my addendum.


-- JonL --