guile-devel
[Top][All Lists]
Advanced

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

Re: Throw and catch, implications for error recovery


From: Derek Peschel
Subject: Re: Throw and catch, implications for error recovery
Date: Thu, 20 Nov 2008 14:28:17 -0800
User-agent: Mutt/1.2.5.1i

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]