[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
unwind_protect & try/catch combined corner case
From: |
John W. Eaton |
Subject: |
unwind_protect & try/catch combined corner case |
Date: |
Thu, 7 Jan 2010 14:06:09 -0500 |
On 7-Jan-2010, Jaroslav Hajek wrote:
| consider this script which mixes unwind_protect and try/catch in a
| not-really-neat way:
| unwind_protect
| try
| unwind_protect
| fdisp (stderr, "press Ctrl-C");
| pause (3)
| #for i = 1:100000
| # fprintf (stderr, "\r%d", i);
| #endfor
| unwind_protect_cleanup
| fprintf (stderr, "\n");
| fdisp (stderr, "cleanup inner");
| error ("raise error");
| end_unwind_protect
| catch
| fdisp (stderr, "caught error");
| end_try_catch
| fdisp (stderr, "intermediate");
| unwind_protect_cleanup
| fdisp (stderr, "cleanup outer");
| end_unwind_protect
| fdisp (stderr, "outer normal");
|
| what should it do?
Since I copied this idea from Emacs Lisp, I decided to check to see
what Emacs would do. In the Emacs Lisp manual, it says
-- Special Form: unwind-protect body-form cleanup-forms...
`unwind-protect' executes BODY-FORM with a guarantee that the
CLEANUP-FORMS will be evaluated if control leaves BODY-FORM, no
matter how that happens. BODY-FORM may complete normally, or
execute a `throw' out of the `unwind-protect', or cause an error;
in all cases, the CLEANUP-FORMS will be evaluated.
If BODY-FORM finishes normally, `unwind-protect' returns the value
of BODY-FORM, after it evaluates the CLEANUP-FORMS. If BODY-FORM
does not finish, `unwind-protect' does not return any value in the
normal sense.
Only BODY-FORM is protected by the `unwind-protect'. If any of
the CLEANUP-FORMS themselves exits nonlocally (via a `throw' or an
error), `unwind-protect' is _not_ guaranteed to evaluate the rest
of them. If the failure of one of the CLEANUP-FORMS has the
potential to cause trouble, then protect it with another
`unwind-protect' around that form.
The number of currently active `unwind-protect' forms counts,
together with the number of local variable bindings, against the
limit `max-specpdl-size' (*note Local Variables: Definition of
max-specpdl-size.).
So it should be expected that some care is needed if an error could
occur in the cleanup block.
For your example with an interrupt, I think it is OK if errors are not
handled after the interrupt. But all cleanup blocks should be
executed in the proper sequence. As you said in a later message, the
point of interrupt is to get back to the top-level as quickly as
possible while safely cleaning up along the way.
If your example is changed to have an error instead of an interrupt in
the first part of the unwind-protect block, like this:
unwind_protect
try
unwind_protect
error ("first error");
unwind_protect_cleanup
fprintf (stderr, "\n");
fdisp (stderr, "cleanup inner");
x = lasterror ();
error ("raise error: %s", x.message);
end_unwind_protect
catch
x = lasterror ();
fprintf (stderr, "caught error: %s\n", x.message);
end_try_catch
fdisp (stderr, "intermediate");
unwind_protect_cleanup
fdisp (stderr, "cleanup outer");
end_unwind_protect
fdisp (stderr, "outer normal");
then I see the same behavior with your code as I did with the older
unwind protect implementation, and it seems like the correct thing to
do.
jwe
- unwind_protect & try/catch combined corner case, Jaroslav Hajek, 2010/01/07
- Re: unwind_protect & try/catch combined corner case, Søren Hauberg, 2010/01/07
- Re: unwind_protect & try/catch combined corner case, Jaroslav Hajek, 2010/01/07
- Re: unwind_protect & try/catch combined corner case, Søren Hauberg, 2010/01/07
- Re: unwind_protect & try/catch combined corner case, Jaroslav Hajek, 2010/01/07
- Re: unwind_protect & try/catch combined corner case, Søren Hauberg, 2010/01/07
- Re: unwind_protect & try/catch combined corner case, Jaroslav Hajek, 2010/01/07
- Re: unwind_protect & try/catch combined corner case, Søren Hauberg, 2010/01/07
unwind_protect & try/catch combined corner case,
John W. Eaton <=