Re: Resumable exceptions

2008-08-21 Thread Stephen Weeks
Not long ago, Patrick R. Michaud proclaimed...
 Here's a simple test for resumable exceptions that I'm trying
 to get to work.  I'm probably coding/understanding something wrong, 
 so any suggestions or pointers would be greatly appreciated.
 
 .sub main :main
 push_eh catcher
 'foo'()
 pop_eh
 say 'ok 4'
 .return ()
   catcher:
 .get_results ($P0, $S0)
 $P1 = $P0['retcont']
 $P1()
 .end
 
 .sub 'foo'
 say 'ok 1'
 $P0 = new 'Exception'
 throw $P0
 say 'ok 2'
 $P0 = new 'Exception'
 throw $P0
 say 'ok 3'
 .end
 
 What I'm trying to do is to test the ability to resume after
 exceptions thrown by Cfoo.  The Cmain sub above sets up
 a handler to catch exceptions, then calls Cfoo.  The handler
 simply resumes any exception that is caught.  The Cfoo sub
 prints 'ok 1', throws an exception, prints 'ok 2', throws another
 exception, and prints 'ok 3'.
 
 I can resume the first exception but not the second:
 
 $ ./parrot x.pir
 ok 1
 ok 2
 No exception handler and no message
 current instr.: 'foo' pc 46 (x.pir:20)
 called from Sub 'main' pc 29 (x.pir:10)
 $
 
 Suggestions and corrections to my code welcomed.

Check RT #58170 for this.  Let me know if you need more detail on what's
happening.


Re: Resumable exceptions

2008-08-20 Thread Allison Randal

Patrick R. Michaud wrote:


What I'm trying to do is to test the ability to resume after
exceptions thrown by Cfoo.  The Cmain sub above sets up
a handler to catch exceptions, then calls Cfoo.  The handler
simply resumes any exception that is caught.  The Cfoo sub
prints 'ok 1', throws an exception, prints 'ok 2', throws another
exception, and prints 'ok 3'.

I can resume the first exception but not the second:

$ ./parrot x.pir
ok 1
ok 2
No exception handler and no message
current instr.: 'foo' pc 46 (x.pir:20)
called from Sub 'main' pc 29 (x.pir:10)
$

Suggestions and corrections to my code welcomed.


The old exception system deleted a handler as soon as it was retrieved 
for an exception. For backward-compatibility, the new exception system 
replicates that mis-feature. The problem is, if you end up throwing an 
exception in the middle of handling another one, and didn't mark the 
handler somehow, you can easily get an infinite loop of thrown 
exceptions (when the handler gets some data it didn't expect from the 
second exception, and so throws another exception).


In an ideal world:

a) every exception handler would first check the type of the exception 
it was passed, and rethrow any exceptions it can't handle.


b) exception handlers would only be deleted by 'pop_eh', and otherwise 
would simply pass out of scope after leaving the context where they were 
defined.


Since (a) has to be in place before (b) can work, it was delayed.

(And I just changed the name of the 'retcont' attribute to 'resume', to 
make it a little clearer.)


Allison


Re: resumable exceptions and LEAVE/KEEP/UNDO blocks

2007-03-05 Thread Larry Wall
On Mon, Mar 05, 2007 at 01:06:46PM +, Daniel Hulme wrote:
: What happens if a resumable exception is propagated through a block with
: a LEAVE, KEEP, or UNDO block? S04 seems to be a bit vague on this point.
: It strikes me that what we want it to do is not execute them when the
: exception is propagated, because we don't know whether it's going to be
: resumed or not. If the exception is resumed by its handler, then that's
: fine, as we can call the blocks at the usual time (when the blocks they
: are attached to exit). If the exception is caught and handled and not
: resumed, that would leave us with having to find all the LEAVE c.
: blocks and call them in the right order when the exception handler
: exits.
: 
: In either case, it looks like you have a problem. LEAVE c. blocks will
: often be used for things like database transactions, where we want to
: ensure that some lock obtained on entering the block is released
: promptly regardless of how the control flow jumps about. In such a
: context, throwing a resumable exception that skips the LEAVE block,
: farts about doing some potentially long computation in a higher-up
: scope, and only calls the LEAVE block to release the lock at some later
: date, seems to be far from the best choice. Sure, we can warn
: programmers to make their resumable-exception handlers short, or to only
: throw non-resumable exceptions from blocks that are likely to be called
: in such circumstances. I suppose that would be an acceptable resolution,
: but it has an aura of non--re-entrant signal handlers about it, so it
: seems like the sort of thing I would like to avoid if anyone is clever
: enough to think of something else to do.

I don't see a problem here.  I think you maybe missed the bit that says:

A CCATCH block sees the lexical scope in which it was defined, but
its caller is the dynamic location that threw the exception.  That is,
the stack is not unwound until some exception handler chooses to
unwind it by handling the exception in question.

Exiting blocks are not run until the decision is made to unwind the stack,
which is *after* the exception handlers are run.  So all the exception
trampoline has to do to resume is just return; the resume continuation
doesn't really have to be a real continuation in this case.

: BTW, if one is handling a resumable exception, how does one resume it? I
: couldn't find anything explaining how. Having a .resume method (or some
: cutesier name) on the Resumable role would seem to make sense.

To resume a resumable exception the correct thing to do is very
likely nothing.  The outermost warning handler is what generally
resumes otherwise uncaught resumables.  If you catch a warning,
it defaults to resuming when handled unless you rethrow it as fatal.

Larry


Re: resumable exceptions and LEAVE/KEEP/UNDO blocks

2007-03-05 Thread Daniel Hulme
On Mon, Mar 05, 2007 at 09:01:13AM -0800, Larry Wall wrote:
 I don't see a problem here.  I think you maybe missed the bit that says:
 
 A CCATCH block sees the lexical scope in which it was defined, but
 its caller is the dynamic location that threw the exception.  That is,
 the stack is not unwound until some exception handler chooses to
 unwind it by handling the exception in question.

Yes, I did. I was grepping specifically for the bit on resumable
exceptions and the quoted bit is 80 lines up so I missed it completely.
Thanks for pointing me at it.

[...]
 To resume a resumable exception the correct thing to do is very
 likely nothing.  The outermost warning handler is what generally
 resumes otherwise uncaught resumables.  If you catch a warning,
 it defaults to resuming when handled unless you rethrow it as fatal.

OK, that makes sense.

The reason that came up was because on Friday I had a good idea for a
language feature that would have made a task I had been doing that day
much easier. When I checked the spec, though, I found out it was already
in. This is happening increasingly often, which should be reassuring to
all concerned.

-- 
Listen to your users, but ignore what they say. - Nathaniel Borenstein
http://surreal.istic.org/  Calm down, it's only ones and zeroes.


signature.asc
Description: Digital signature


Re: [unclassified] Re: resumable exceptions

2006-06-17 Thread John M. Dlugosz
I was involved in the C++ standardization process, and argued for 
resumption as opposed to termination only in exceptions.  I was somewhat 
of a pioneer, implementing C++ exceptions for my team to use before 
commercial compilers had them.  After all, why start a new project with 
an old paradigm?


Anyway, as passionate as I was about resumption, or at least making it 
not impossible to implement resumption, at the next ANSI meeting the 
terminate-only camp made compelling arguments. 

I don't remember what the killer argument was.  But I do remember bits 
and pieces:  people with real-world experience on systems that have 
resumable exceptions in some form ended up never using them; it 
complicates the implementation; it is not necessary since callbacks fill 
that role already (e.g. new_handler instead of resuming from the 
bad_alloc exception); and the semantic concepts of what an exception 
means.  To elaborate, the code throws when it can't deal with the 
situation.  What does it mean if the throw worked like a function call 
and returned?  Code would have to watch out for that, which defeats the 
point of making the exception a clean get-away.  Really, after fixing 
something the function has to start over at the top; e.g. try allocating 
again... that's what a loop around the whole try/catch does, and is 
today common practice! 

So on providing different places to jump to depending on whether the 
exception is fixed or not fixed, how is that different from a normal 
catch block which can re-throw or drop out?


Consider the error upon trying to open a file.  If the open command 
contains a callback handler as part of itself, it can try again and 
eventually return, transparantly to the caller who just sees that the 
file was (eventually) opened.  But what if the caller needs to back up 
and repeat some steps because of that failure, to get another running 
start at the command so to speak?  That's what you can do with a 
mechanism more elaborate than the callback built into the command.  But 
you can do that with a try/catch now, having termination semantics, 
already.  Besides syntactic sugar, how is resuming different from that?


--John

Larry Wall wrote:


On Wed, Jun 14, 2006 at 08:59:02PM -0700, Chip Salzenberg wrote:
: Are Parrot exceptions now, in fact, resumable?  If they are, is that
: important?  Is anyone actually resuming execution after exception handlers
: are called?  I think we _can_ keep resumability, but I'm not sure I want us
: to, and I definitely don't want to bother if no one wants it.

The current thought for Perl 6 is that warnings are essentially just
resumable control exceptions that by default are caught only by the
outermost exception handler, which by default resumes them.  But any
exception handler in the dynamic scope may then catch one and turn
it fatal.  This gives us dynamic as well as lexical control of warnings
without inventing a mechanism separate from existing control exceptions.

On the other hand, I think we've also said that exceptions are
resumable only if the thrower includes as part of the exception
object a continuation to resume at, which presumably warn() does.
So maybe you don't need to do anything special to make exceptions
resumable for Perl 6, assuming throwing the exception doesn't clobber
the continuation somehow.

On the gripping hand, it looks like this is missing from the specs...

Larry

 






Re: [unclassified] Re: resumable exceptions

2006-06-17 Thread Larry Wall
On Fri, Jun 16, 2006 at 10:51:24PM -0500, John M. Dlugosz wrote:
: Anyway, as passionate as I was about resumption, or at least making it 
: not impossible to implement resumption, at the next ANSI meeting the 
: terminate-only camp made compelling arguments. 

Well, interestingly, I used to be in the terminate-only camp.

: I don't remember what the killer argument was.  But I do remember bits 
: and pieces:  people with real-world experience on systems that have 
: resumable exceptions in some form ended up never using them; it 
: complicates the implementation; it is not necessary since callbacks fill 
: that role already (e.g. new_handler instead of resuming from the 
: bad_alloc exception); and the semantic concepts of what an exception 
: means.  To elaborate, the code throws when it can't deal with the 
: situation.  What does it mean if the throw worked like a function call 
: and returned?

In general, it would simply mean that you called warn() instead
of fail().  If you call warn() you're expecting to gamely attempt
to continue.  If you call fail(), you're not expecting to return.
Warning is all about expressing misgivings when you're not sure.
If we throw a warning like we throw an exception, then someone in
the dynamic context may well be more sure than we are whether the
warning should be suppressed or fatalized.

: Code would have to watch out for that, which defeats the 
: point of making the exception a clean get-away.  Really, after fixing 
: something the function has to start over at the top; e.g. try allocating 
: again... that's what a loop around the whole try/catch does, and is 
: today common practice! 
: 
: So on providing different places to jump to depending on whether the 
: exception is fixed or not fixed, how is that different from a normal 
: catch block which can re-throw or drop out?

It doesn't give the code in question the option of raising objections
without giving up.  How would you like it if the only way you could
complain to your management was by turning in a letter of resignation
and hoping they'll rehire you immediately?  Instead, we use office
memos/email that can convey either warnings or resignations.

: Consider the error upon trying to open a file.  If the open command 
: contains a callback handler as part of itself, it can try again and 
: eventually return, transparantly to the caller who just sees that the 
: file was (eventually) opened.  But what if the caller needs to back up 
: and repeat some steps because of that failure, to get another running 
: start at the command so to speak?  That's what you can do with a 
: mechanism more elaborate than the callback built into the command.  But 
: you can do that with a try/catch now, having termination semantics, 
: already.  Besides syntactic sugar, how is resuming different from that?

Sure, and that's what fatal exceptions are good for.  If you are giving
up, throwing a terminate-only exception is exactly what you want to do.

But look at this from the other direction--how do we unify warnings
with exceptions such that people aren't forced to invent out-of-band
warning systems that duplicate most of what throwing exceptions
already does?

In a sense, the whole idea of resumably exception is looking at
it sideways from what you really want.  An exception is just some
bad news that you're trying to pass up the dynamic stack to get more
direction on.  Even if you don't define resumably exceptions at all, in
a language where continuations are first class objects, the *throwing*
code can install one of those into any exception that can hold one,
and bang, you've got resumable exceptions whether you want them or not.

The point you made earlier is one that I agree with, which is that the
*user* interface has to be clear at the point of the throw.  You don't
want to define your interface so that fail() ever returns.  It's like
a return: it documents that the following statement is not reached.
But we can treat warn() as a variant that does document the fact that
it installs a resume continuation, and then attempts to throw a kind of
exception that will be resumed by default.

We could go as far as to have another variant, despair() or some such,
that throws a resumable exception that is not expected to resume
by default, but someone in the dynamic scope might call our resume
continuation anyway.  So that function call would document that we
*probably* won't resume here but don't count on it.  If we do resume,
we'll still try to carry on somehow.

Note also that this cleans up the local $SIG{__WARN__} mess of Perl 5.
Perl 5 compartmentalized warnings from exceptions, but we're just not
gonna do that anymore.  It makes much more sense to unify them, I think.

The latest version of S04 documents how all this is expected to work,
in particular the notion that warnings are just considered control
exceptions so that they bypass most CATCH blocks but can be managed
via CONTROL blocks.

Larry


Re: resumable exceptions

2006-06-15 Thread Larry Wall
On Wed, Jun 14, 2006 at 08:59:02PM -0700, Chip Salzenberg wrote:
: Are Parrot exceptions now, in fact, resumable?  If they are, is that
: important?  Is anyone actually resuming execution after exception handlers
: are called?  I think we _can_ keep resumability, but I'm not sure I want us
: to, and I definitely don't want to bother if no one wants it.

The current thought for Perl 6 is that warnings are essentially just
resumable control exceptions that by default are caught only by the
outermost exception handler, which by default resumes them.  But any
exception handler in the dynamic scope may then catch one and turn
it fatal.  This gives us dynamic as well as lexical control of warnings
without inventing a mechanism separate from existing control exceptions.

On the other hand, I think we've also said that exceptions are
resumable only if the thrower includes as part of the exception
object a continuation to resume at, which presumably warn() does.
So maybe you don't need to do anything special to make exceptions
resumable for Perl 6, assuming throwing the exception doesn't clobber
the continuation somehow.

On the gripping hand, it looks like this is missing from the specs...

Larry