* Throw and catch, implications for error recovery
@ 2008-11-20 0:03 Derek Peschel
2008-11-20 9:54 ` Andy Wingo
0 siblings, 1 reply; 3+ messages in thread
From: Derek Peschel @ 2008-11-20 0:03 UTC (permalink / raw)
To: guile-devel
Hi everybody,
Neil Jerram explained some features of the Guile debugging framework and
then suggested I send further questions to guile-devel. We talked about
error recovery as a desirable feature -- being able to continue a
computation in some way after it hits an error. The error may be caused
by the computation or by running an "eval" or "tweak" command. Last I
checked, no recovery is possible in either case.
Presumably the upward-only implementation of throw and catch is the
problem (or part of it). Is that true? Is there an easy rule for
determining which stack frames become non-recoverable? If that's too
vague a question, I can send specific examples, though I don't have the
mental model to determine the state of the system for each example.
(What continuations exist and their contents, which continuations have
access to other continuations, other data like saved error data, etc.)
Thanks,
-- Derek
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Throw and catch, implications for error recovery
2008-11-20 0:03 Throw and catch, implications for error recovery Derek Peschel
@ 2008-11-20 9:54 ` Andy Wingo
2008-11-20 22:28 ` Derek Peschel
0 siblings, 1 reply; 3+ messages in thread
From: Andy Wingo @ 2008-11-20 9:54 UTC (permalink / raw)
To: Derek Peschel; +Cc: guile-devel
Hi Derek,
On Thu 20 Nov 2008 01:03, Derek Peschel <dpeschel@eskimo.com> writes:
> Presumably the upward-only implementation of throw and catch is the
> problem (or part of it). Is that true? Is there an easy rule for
> determining which stack frames become non-recoverable?
It's an interesting question.
I don't know how much the debugger gives you -- I haven't really gotten
into using it yet. But what I would want would be that if you install a
pre-unwind handler that captures the continuation, in theory you should
be able to munge that continuation, restarting certain frames with
different arguments, or different expressions entirely.
In practice though, given that we use the C stack, there are only some
points at which setjmp() has been called, and thus only those places to
which we know how to unwind. Practically speaking, this occurs only at
calls to `catch' and `call-with-current-continuation'. So you can
restart where a continuation is captured, or from the start of a catch
block.
Guile should probably add a raise-continuable as r6 has done, to give
the user a better-supported (and cheaper) restart mechanism.
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Throw and catch, implications for error recovery
2008-11-20 9:54 ` Andy Wingo
@ 2008-11-20 22:28 ` Derek Peschel
0 siblings, 0 replies; 3+ messages in thread
From: Derek Peschel @ 2008-11-20 22:28 UTC (permalink / raw)
To: Andy Wingo
On Thu, Nov 20, 2008 at 10:54:45AM +0100, Andy Wingo wrote:
> I don't know how much the debugger gives you -- I haven't really gotten
> into using it yet. But what I would want would be that if you install a
An overview of the relevant modules might help you find your way around the
code and documentation:
(ice-9 debug) is a trace utility, not compatible with the other modules.
(ice-9 debugger) works with stdin/stdout like the REPL and allows
inspecting saved error state.
(ice-9 debugging) extends (ice-9 debugger) with program-control commands
for stepping and evaluation and so on.
GDS, the Emacs interface, uses (ice-9 debugging) and some other code;
its features are mostly compatible with the (ice-9 debugging) commands
with a few exceptions -- e.g. (ice-9 debugging) has no "tweak" command
and GDS has no "finish" command.
The modules and documentation were written by different people at different
times. The documentation is still being reorganized and fleshed out.
Check the repository files as well as the released versions.
These are some of the major features:
The trap infrastructure for starting the debugger on certain events.
In the debugger, evaluating code in the debuggee's context.
Tweaking, which is evaluating code and causing the debuggee to skip
an expression and reenter the debugger (amounting to one-time
replacement of the skipped expression by the tweak argument)
Saving of the stack from the last error, and inspecting it in the
debugger.
> pre-unwind handler that captures the continuation, in theory you should
> be able to munge that continuation, restarting certain frames with
> different arguments, or different expressions entirely.
Are pre-unwind handlers the same as throw handlers? The thing is, the
_debuggee_ causes the error and starts the unwinding. (Except the debuger
uses lazy-catch which is different than regular catch, so we have to define
what kind of unwinding is actually happening.) Can the debugger supply a
handler that the debuggee will use? What if the debuggee wants to use its
own handlers?
> In practice though, given that we use the C stack, there are only some
> points at which setjmp() has been called, and thus only those places to
> which we know how to unwind. Practically speaking, this occurs only at
> calls to `catch' and `call-with-current-continuation'. So you can
> restart where a continuation is captured, or from the start of a catch
> block.
Are you saying that normal Scheme->Scheme procedure calls don't capture
continuations? And are you saying it's the existence of a catch handler
in the debugger that allows the debugger to continue running after the
error? (not surprising, it's what I suspected myself)
The "evaluate in program's context" feature can work with any frame on the
stack, so when the program is stopped without an error, stack frames are
accessible individually. But I don't know if they are equivalent to
continuations or if a better debugger could take advantage of any
equivalence.
Do you know if the C function for "throw" calls longjmp? (I don't have the
code in front of me and I want to get this message out quickly anyway.)
You worried me because when I think of setjmp/longjmp I think of throwing
away stack frames. Guile doesn't do that; it uses setjmp/longjmp in unusual
ways. For example, it copies the stack being thrown away. So if we are
going to talk about the C layer then we need to know how it really works
in Guile's case, which I don't.
> Guile should probably add a raise-continuable as r6 has done, to give
> the user a better-supported (and cheaper) restart mechanism.
Thanks, that's a bit of the kind of answer I was looking for. Then errors
need to call raise-continuable, of course.
Here are some more specific cases.
1. I'm stopped in my code, I use the debugger to evaluate something in a
frame's context, and the evaluation causes an error due to a typo.
I'd like to be able to evaluate more expressions in the same context.
2. My function f1 calls a function f2 with the wrong number of arguments.
This is a situation where continuing or the "tweak" feature would
really be handy, so I can back up in f1 to before the call and then
substitute a new call. Or perhaps I could redefine f1, back up in f1's
parent to before the call of f1, and step forward through the call again.
(In a simple architecture where stack frames correspond to functions and
have PCs that point into a block of code, backing up would literally be
moving the PC backward. I don't know how it could work in Guile.)
-- Derek
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-11-20 22:28 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-20 0:03 Throw and catch, implications for error recovery Derek Peschel
2008-11-20 9:54 ` Andy Wingo
2008-11-20 22:28 ` Derek Peschel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).