On Mon, Dec 7, 2009 at 9:28 AM, Nicholas Clark <[email protected]> wrote:
> Is the inferior runloop problem that
>
> 1: the exception fires
> 2: the exception handler is started in an inferior runloop
> 3: the exception handler completes by resuming execution
> 4: *that* execution resumes still within the inferior runloop
> 5: the inferior runloop completes the program to exit
> 6: the inferior runloop exits
> 7: the original runloop continues from the point of the exception
yes. This is one manifestation of it.
> in which case, what seems to be needed to allow control exceptions to affect
> control flow is
>
> 1: that the exception handler (or at least the last part of it) runs in
> *the same runloop* as where it is declared
> 2: (by implication) the exception handler is not allowed to return control to
> the point where the exception is thrown
Something has to give, and so far every possibly solution that's been
suggested is unacceptable to one or more of our users. Here are some
possible solutions that fit this pattern, and I'm purposefully
including some Really Bad ones for reference:
1) Prohibit handlers declared in one runloop from catching exceptions
thrown in another. (bad, but quick and solid).
2) Exception handlers must always execute in the runloop where they
are defined (prevents resuming to nested runloops and creates problems
with handlers defined in a nested runloop)
3) Completely refactor Parrot to disallow nested runloops (will
require months or years of work, if it's possible at all)
4) Massive refactor of exception handlers to enforce large numbers of
explicit checks for crossed runloop boundaries and manual unwinding of
the C stack when they are detected. (Doable, but will create lots of
intractable "Grey Areas" where bugs will live forever, and will kill
performance across the board)
5) Disallow throwing non-fatal exceptions from certain cases such as
":load" or ":init" functions (only a partial solution, it only covers
the easy cases shown using the PIR compreg)
6) Add a system where exceptions thrown from one runloop towards
another are caught and locally rethrown. (Requires
potentially-expensive detection of such cases, and also prevents
resuming back to the internal runloop).
5) Demand (and enforce) all exception handlers have explicit end
points, to prevent execution from just continuing to the end of the
program: step 5 in the list above. This would require massive
refactoring of PIR code to create a clear demarcation between handlers
and other code. Sub-based handlers is just one implementation of this
that uses existing language features to enforce the beginning and end
of the handler
I'm sure there are a few more solutions that could be found too, but
none of them are going to be 100% good to 100% of our users. I think
we're going to have to start making sacrifices at the alter here,
there's no way we're going to solve this problem in a reasonable way
and keep every semantical nuance that we have now.
> Effectively the style of exception handler that is needed here is much like
> C's longjmp() - a non-local goto to the point of declaration of the exception
> handler, and then the exception handler can make a goto (local or not) to
> continue. Not like Perl 5's $SIG{__DIE__} or $SIG{__WARN__} hooks.
Parrot does use longjmps in some places for exception handling. What
longjmps do not allow us to do is to jump down the stack to a frame
that has already exited. This means we can't resume into a child
runloop. There may be no way to avoid that.
--Andrew Whitworth
_______________________________________________
http://lists.parrot.org/mailman/listinfo/parrot-dev