unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* saving and restoring the error stack trace
@ 2006-08-24 19:34 Marco Maggi
  2006-08-24 21:53 ` Neil Jerram
  0 siblings, 1 reply; 15+ messages in thread
From: Marco Maggi @ 2006-08-24 19:34 UTC (permalink / raw)


Ciao,

  I am interfacing the GSL ordinary differential
equations solver with Guile. I have the following
stack of invocations:

my-scheme-implemented-scheme-function
|
 ->my-C-implemented-scheme-function
   |
    ->gsl_odeiv_evolve_apply
      |
       ->my_C_callback
         |
          ->scm_internal_catch
            |
             ->my_other_C_callback
               |
                ->my-other-scheme-impl-scheme-function

If an error occurs in the invocation of
my-other-scheme-impl-scheme-function I want a
full stack trace of the error be shown to the
user that invoked my-scheme-implemented-scheme-function
at the REPL.

I cannot let the dynwind mechanism pass through
gsl_odeiv_evolve_apply, that is why I am using
scm_internal_catch. But in this way if I rethrow
the exception in my-C-implemented-scheme-function
I loose the stack trace that includes the body
of my-other-scheme-impl-scheme-function.

For the ones that know how Tcl works: what I want
is the same as saving the "errorInfo" global variable
and restoring it later.

Is there a way?

--
Marco Maggi

"They say jump!, you say how high?"
Rage Against the Machine - "Bullet in the Head"



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-08-24 19:34 saving and restoring the error stack trace Marco Maggi
@ 2006-08-24 21:53 ` Neil Jerram
  0 siblings, 0 replies; 15+ messages in thread
From: Neil Jerram @ 2006-08-24 21:53 UTC (permalink / raw)
  Cc: guile-user

"Marco Maggi" <marco.maggi-ipsu@poste.it> writes:

> If an error occurs in the invocation of
> my-other-scheme-impl-scheme-function I want a
> full stack trace of the error be shown to the
> user that invoked my-scheme-implemented-scheme-function
> at the REPL. 

> Is there a way?

Yes, and I'm in the process of writing this up properly for the
manual.  How quickly do you need an answer?

Regards,
     Neil



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
@ 2006-08-25  9:39 Marco Maggi
  2006-08-27 12:53 ` Neil Jerram
  0 siblings, 1 reply; 15+ messages in thread
From: Marco Maggi @ 2006-08-25  9:39 UTC (permalink / raw)


"Neil Jerram" wrote:
>"Marco Maggi" <marco.maggi-ipsu@poste.it> writes:
>> If an error occurs in the invocation of
>> my-other-scheme-impl-scheme-function I want a
>> full stack trace of the error be shown to the
>> user that invoked my-scheme-implemented-scheme-function
>> at the REPL.
>
>> Is there a way?

> Yes, and I'm in the process of writing this up
> properly for the manual.
> How quickly do you need an answer?

I am in no hurry at all. Take your time.
Thank You.

--
Marco Maggi

"They say jump!, you say how high?"
Rage Against the Machine - "Bullet in the Head"



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-08-25  9:39 Marco Maggi
@ 2006-08-27 12:53 ` Neil Jerram
  2006-08-28 22:21   ` Neil Jerram
  0 siblings, 1 reply; 15+ messages in thread
From: Neil Jerram @ 2006-08-27 12:53 UTC (permalink / raw)
  Cc: guile-user

"Marco Maggi" <marco.maggi-ipsu@poste.it> writes:

> "Neil Jerram" wrote:
>>"Marco Maggi" <marco.maggi-ipsu@poste.it> writes:
>>> If an error occurs in the invocation of
>>> my-other-scheme-impl-scheme-function I want a
>>> full stack trace of the error be shown to the
>>> user that invoked my-scheme-implemented-scheme-function
>>> at the REPL. 
>>
>>> Is there a way?
>
>> Yes, and I'm in the process of writing this up
>> properly for the manual.
>> How quickly do you need an answer?
>
> I am in no hurry at all. Take your time.

Thanks; I expect to have some draft text for you by end tomorrow.

Regards,
     Neil



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-08-27 12:53 ` Neil Jerram
@ 2006-08-28 22:21   ` Neil Jerram
  2006-09-07  9:02     ` Volkan YAZICI
  0 siblings, 1 reply; 15+ messages in thread
From: Neil Jerram @ 2006-08-28 22:21 UTC (permalink / raw)
  Cc: guile-user

Neil Jerram <neil@ossau.uklinux.net> writes:

> Thanks; I expect to have some draft text for you by end tomorrow.

Draft text is below; please let me know your thoughts on it - most
importantly, of course, whether it answers your question!

Regards,
     Neil


5.21.2 Debugging when an error occurs
-------------------------------------

A common requirement is to be able to show as much useful context as
possible when a Scheme program hits an error.  The most immediate
information about an error is the kind of error that it is - such as
"division by zero" - and any parameters that the code which signalled
the error chose explicitly to provide.  This information originates with
the `error' or `throw' call (or their C code equivalents, if the error
is detected by C code) that signals the error, and is passed
automatically to the handler procedure of the innermost applicable
`catch', `lazy-catch' or `with-throw-handler' expression.

5.21.2.1 Intercepting basic error information
.............................................

Therefore, to catch errors that occur within a chunk of Scheme code, and
to intercept basic information about those errors, you need to execute
that code inside the dynamic context of a `catch', `lazy-catch' or
`with-throw-handler' expression, or the equivalent in C.  In Scheme,
this means you need something like this:

     (catch #t
            (lambda ()
              ;; Execute the code in which
              ;; you want to catch errors here.
              ...)
            (lambda (key . parameters)
              ;; Put the code which you want
              ;; to handle an error here.
              ...))

The `catch' here can also be `lazy-catch' or `with-throw-handler'; see
*Note Throw Handlers:: and *Note Lazy Catch:: for the details of how
these differ from `catch'.  The `#t' means that the catch is applicable
to all kinds of error; if you want to restrict your catch to just one
kind of error, you can put the symbol for that kind of error instead of
`#t'.  The equivalent to this in C would be something like this:

     SCM my_body_proc (void *body_data)
     {
       /* Execute the code in which
          you want to catch errors here. */
       ...
     }

     SCM my_handler_proc (void *handler_data,
                          SCM key,
                          SCM parameters)
     {
       /* Put the code which you want
          to handle an error here. */
       ...
     }

     {
       ...
       scm_c_catch (SCM_BOOL_T,
                    my_body_proc, body_data,
                    my_handler_proc, handler_data,
                    NULL, NULL);
       ...
     }

Again, as with the Scheme version, `scm_c_catch' could be replaced by
`scm_internal_lazy_catch' or `scm_c_with_throw_handler', and
`SCM_BOOL_T' could instead be the symbol for a particular kind of error.

5.21.2.2 Capturing the full error stack
.......................................

The other interesting information about an error is the full Scheme
stack at the point where the error occurred; in other words what
innermost expression was being evaluated, what was the expression that
called that one, and so on.  If you want to write your code so that it
captures and can display this information as well, there are two
important things to understand.

   Firstly, the stack at the point of the error needs to be explicitly
captured by a `make-stack' call (or the C equivalent `scm_make_stack').
The Guile library does not do this "automatically" for you, so you
will need to write code with a `make-stack' or `scm_make_stack' call
yourself.  (We emphasise this point because some people are misled by
the fact that the Guile interactive REPL code _does_ capture and
display the stack automatically.  But the Guile interactive REPL is
itself a Scheme program(1) running on top of the Guile library, and
which uses `catch' and `make-stack' in the way we are about to describe
to capture the stack when an error occurs.)

   Secondly, in order to capture the stack effectively at the point
where the error occurred, the `make-stack' call must be made before
Guile unwinds the stack back to the location of the prevailing catch
expression.  This means that the `make-stack' call must be made within
the handler of a `lazy-catch' or `with-throw-handler' expression, or
the optional "pre-unwind" handler of a `catch'.  (For the full story of
how these alternatives differ from each other, see *Note Exceptions::.
The main difference is that `catch' terminates the error, whereas
`lazy-catch' and `with-throw-handler' only intercept it temporarily and
then allow it to continue propagating up to the next innermost handler.)

   So, here are some examples of how to do all this in Scheme and in C.
For the purpose of these examples we assume that the captured stack
should be stored in a variable, so that it can be displayed or
arbitrarily processed later on.  In Scheme:

     (let ((captured-stack #f))
       (catch #t
              (lambda ()
                ;; Execute the code in which
                ;; you want to catch errors here.
                ...)
              (lambda (key . parameters)
                ;; Put the code which you want
                ;; to handle an error after the
                ;; stack has been unwound here.
                ...)
              (lambda (key . parameters)
                ;; Capture the stack here:
                (set! captured-stack (make-stack #t))))
       ...
       (if captured-stack
           (begin
             ;; Display or process the captured stack.
             ...))
       ...)

And in C:

     SCM my_body_proc (void *body_data)
     {
       /* Execute the code in which
          you want to catch errors here. */
       ...
     }

     SCM my_handler_proc (void *handler_data,
                          SCM key,
                          SCM parameters)
     {
       /* Put the code which you want
          to handle an error after the
          stack has been unwound here. */
       ...
     }

     SCM my_preunwind_proc (void *handler_data,
                            SCM key,
                            SCM parameters)
     {
       /* Capture the stack here: */
       *(SCM *)handler_data = scm_make_stack (SCM_BOOL_T, SCM_EOL);
     }

     {
       SCM captured_stack = SCM_BOOL_F;
       ...
       scm_c_catch (SCM_BOOL_T,
                    my_body_proc, body_data,
                    my_handler_proc, handler_data,
                    my_preunwind_proc, &captured_stack);
       ...
       if (captured_stack != SCM_BOOL_F)
       {
         /* Display or process the captured stack. */
         ...
       }
       ...
     }

Note that you don't have to wait until after the `catch' or
`scm_c_catch' has returned.  You can also do whatever you like with the
stack immediately after it has been captured in the pre-unwind handler,
or in the normal (post-unwind) handler.  (Except that for the latter
case in C you will need to change `handler_data' in the
`scm_c_catch(...)' call to `&captured_stack', so that `my_handler_proc'
has access to the captured stack.)

5.21.2.3 Displaying or interrogating the captured stack
.......................................................

Once you have a captured stack, you can interrogate and display its
details in any way that you want, using the `stack-...' and `frame-...'
API described in *Note Examining the Stack:: and *Note Examining Stack
Frames::.

   If you want to print out a backtrace in the same format that the
Guile REPL does, you can use the `display-backtrace' procedure to do so.
You can also use `display-application' to display an individual
application frame - that is, a frame that satisfies the
`frame-procedure?' predicate - in the Guile REPL format.



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
@ 2006-08-29  3:08 dsmich
  2006-09-01  7:34 ` Neil Jerram
  0 siblings, 1 reply; 15+ messages in thread
From: dsmich @ 2006-08-29  3:08 UTC (permalink / raw)
  Cc: guile-user

---- Neil Jerram <neil@ossau.uklinux.net> wrote: 
> Neil Jerram <neil@ossau.uklinux.net> writes:
> 
> > Thanks; I expect to have some draft text for you by end tomorrow.
> 
> Draft text is below; please let me know your thoughts on it - most
> importantly, of course, whether it answers your question!

> 5.21.2 Debugging when an error occurs

   ...

Thank you, thank you!  This bit of documentation has been sorely needed for a long time.  Many people come to Guile from the "C side" with poor or nonexistant Scheme experience.  Usually to add Guile to some C application, which of course throws out the REPL and it's backtracing and error reporting capabilities.  So then when errors happen you have no idea where or how.  Making a C program extended by Guile spit out a proper backtrace is a twisty maze of handlers and catchers, and some of them need to be lazy.  (Lazy? Why would I want a *lazy* handler, I want  a hard-working, full-featured kind of handler, not some wimpy light weight *lazy* handler!)

My point is that getting good backtraces from C is non-obvious and a huge hindrance to people just learning how to use Guile and Scheme.  But that's over now.  Thanks again Neil.

-Dale



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
@ 2006-08-31  6:04 Marco Maggi
  2006-09-01  7:47 ` Neil Jerram
  0 siblings, 1 reply; 15+ messages in thread
From: Marco Maggi @ 2006-08-31  6:04 UTC (permalink / raw)


"Neil Jerram" wrote:
> [...] please let me know your thoughts on it -
> most importantly, of course, whether it answers your
> question!

Making the stack with this:

  s_error_stack = scm_make_stack(SCM_BOOL_T, SCM_EOL);

and using the function (scm_t = SCM):

void
rethrow_error_with_stack (scm_t s_error_stack,
                          scm_t s_error_key,
                          scm_t s_error_args,
                          const char * procname)
{
  scm_t		s_port, s_string, s_stack;
  size_t	len;

  s_stack = scm_make_stack(SCM_BOOL_T, SCM_EOL);
  len =
    scm_to_uint(scm_stack_length(s_error_stack)) -
    scm_to_uint(scm_stack_length(s_stack)) - 1;

  s_port = scm_open_output_string();
  {
    scm_t	s_message =
scm_list_ref(s_error_args,scm_from_uint(1));
    scm_t	s_args    =
scm_list_ref(s_error_args,scm_from_uint(2));

    scm_simple_format(s_port, s_message,
		      (scm_is_eq(SCM_BOOL_F, s_args)? SCM_EOL : s_args));
    scm_newline(s_port);
    scm_display_backtrace(s_error_stack, s_port,
 			  scm_from_uint(len), SCM_UNDEFINED);
    s_string = scm_get_output_string(s_port);
  }
  scm_close_output_port(s_port);
  scm_error_scm(s_error_key, scm_from_locale_string(procname),
		s_string, SCM_BOOL_F,
		scm_list_ref(s_error_args, scm_from_uint(3)));
}

I have error messages like:

Backtrace:
In unknown file:
   ?: 0* [dotest "gsl-ode-error-2.4" #<procedure #f ()> ...]
   ?: 1  (let* () (let* (# #) (let* # #)))
   ...
   ?: 2  (begin (display name) (if (thunk? setup) (setup)) ...)
   ?: 3* (let (# # # ...) (set-current-input-port saved-in) ...)
   ?: 4* (if catch-error (catch #t thunk (lambda (key .
args) key)) (thunk))
   ?: 5  [#<procedure #f ()>]
   ...
   ?: 6  (let* ((result (quote ()))) (if debugging
(newline)) ...)
   ?: 7* [gsl-ode-evolve #<universal GSL SMOB 404697f8>
#:initial-indep-value ...]
   ?: 8  (let-keywords args #f ...)
   ...
   ?: 9  [gsl-p-ode-evolve #<universal GSL SMOB 404697f8>
0.0 ...]

<unnamed port>: In procedure gsl-ode-evolve in expression
(gsl-p-ode-evolve ode initial-indep-value ...):
<unnamed port>: my error message 1 and 2
In unknown file:
   ?: 10* [#<procedure #f (t y)> 0.0 #,(gsl-vector-real 1 2.0)]
   ?: 11* [gsl-ode-invoke-fun 0.0 #,(gsl-vector-real 1 2.0) ...]
   ?: 12  (let* ((o (func t #))) (if (gsl? o) (slot-ref o
(quote v)) ...))
   ?: 13* [#<procedure #f (t y)> 0.0 #,(gvr 1  2.0)]
   ?: 14  [throwing-error]
    ...
   ?: 15  [scm-error my-own-error "sub-throwing-error" ...]

which is not perfect but seems good enough for me.

I am a little annoyed that I have to use a port to
build the backtrace string, and that the args content
is not explicitly documented (that is, I was not
able to find it) even if its content is well defined
in 'scm_error_scm()':

  scm_ithrow (key,
        scm_list_4 (subr, message, args, data), 1);


--
Marco Maggi

"They say jump!, you say how high?"
Rage Against the Machine - "Bullet in the Head"



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-08-29  3:08 dsmich
@ 2006-09-01  7:34 ` Neil Jerram
  0 siblings, 0 replies; 15+ messages in thread
From: Neil Jerram @ 2006-09-01  7:34 UTC (permalink / raw)
  Cc: guile-user

<dsmich@adelphia.net> writes:

> ---- Neil Jerram <neil@ossau.uklinux.net> wrote: 
>
>> 5.21.2 Debugging when an error occurs
>
>    ...
>
> Thank you, thank you!  This bit of documentation has been sorely
> needed for a long time.

That's true.  Over the last few years it's a question that has been
regularly asked on the mailing lists, and never quite definitively
answered.

>  Many people come to Guile from the "C side"
> with poor or nonexistant Scheme experience.  Usually to add Guile to
> some C application, which of course throws out the REPL and it's
> backtracing and error reporting capabilities.  So then when errors
> happen you have no idea where or how.  Making a C program extended
> by Guile spit out a proper backtrace is a twisty maze of handlers
> and catchers, and some of them need to be lazy.  (Lazy? Why would I
> want a *lazy* handler, I want a hard-working, full-featured kind of
> handler, not some wimpy light weight *lazy* handler!)

:-)

> My point is that getting good backtraces from C is non-obvious and a
> huge hindrance to people just learning how to use Guile and Scheme.
> But that's over now.  Thanks again Neil.

Thanks for your kind words.

Regards,
     Neil



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-08-31  6:04 Marco Maggi
@ 2006-09-01  7:47 ` Neil Jerram
  2006-09-01  9:39   ` Ludovic Courtès
  0 siblings, 1 reply; 15+ messages in thread
From: Neil Jerram @ 2006-09-01  7:47 UTC (permalink / raw)
  Cc: guile-user

"Marco Maggi" <marco.maggi-ipsu@poste.it> writes:

> Making the stack with this:
>
>   s_error_stack = scm_make_stack(SCM_BOOL_T, SCM_EOL);
>
> and using the function (scm_t = SCM): [...]
>
> I have error messages like:
>
> Backtrace:
> In unknown file:
>    ?: 0* [dotest "gsl-ode-error-2.4" #<procedure #f ()> ...]
>    ?: 1  (let* () (let* (# #) (let* # #)))
>    ...
>    ?: 2  (begin (display name) (if (thunk? setup) (setup)) ...)
>    ?: 3* (let (# # # ...) (set-current-input-port saved-in) ...)
>    ?: 4* (if catch-error (catch #t thunk (lambda (key .
> args) key)) (thunk))
>    ?: 5  [#<procedure #f ()>]
>    ...
>    ?: 6  (let* ((result (quote ()))) (if debugging
> (newline)) ...)
>    ?: 7* [gsl-ode-evolve #<universal GSL SMOB 404697f8>
> #:initial-indep-value ...]
>    ?: 8  (let-keywords args #f ...)
>    ...
>    ?: 9  [gsl-p-ode-evolve #<universal GSL SMOB 404697f8>
> 0.0 ...]
>
> <unnamed port>: In procedure gsl-ode-evolve in expression
> (gsl-p-ode-evolve ode initial-indep-value ...):
> <unnamed port>: my error message 1 and 2
> In unknown file:
>    ?: 10* [#<procedure #f (t y)> 0.0 #,(gsl-vector-real 1 2.0)]
>    ?: 11* [gsl-ode-invoke-fun 0.0 #,(gsl-vector-real 1 2.0) ...]
>    ?: 12  (let* ((o (func t #))) (if (gsl? o) (slot-ref o
> (quote v)) ...))
>    ?: 13* [#<procedure #f (t y)> 0.0 #,(gvr 1  2.0)]
>    ?: 14  [throwing-error]
>     ...
>    ?: 15  [scm-error my-own-error "sub-throwing-error" ...]
>
> which is not perfect but seems good enough for me.

OK.  Out of interest, though, what changes would you like to the
presentation?  (And, to ask a leading question, do you think that the
way my Emacs interface displays the stack is better or worse than
this?  http://www.ossau.uklinux.net/guile/debugging-demo/shot2.html)

> I am a little annoyed that I have to use a port to
> build the backtrace string,

That just needs getting used to; I'd say that ports are a fantastic
abstraction.  And the C API for a string port is very easy to use,
isn't it?

> and that the args content
> is not explicitly documented (that is, I was not
> able to find it) even if its content is well defined
> in 'scm_error_scm()':
>
>   scm_ithrow (key,
>         scm_list_4 (subr, message, args, data), 1);

Yes, here I completely agree with you.  I've been wondering what to do
about this for ages.  Do you think it can be solved adequately by
precise documentation, or do we need some way of describing the
expected throw args in code; perhaps even construct some kind of
object model around the args with methods for getting the useful bits
of information out?  (Use of which would be optional.)

Regards,
     Neil



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-09-01  7:47 ` Neil Jerram
@ 2006-09-01  9:39   ` Ludovic Courtès
  2006-09-07 22:11     ` Neil Jerram
  0 siblings, 1 reply; 15+ messages in thread
From: Ludovic Courtès @ 2006-09-01  9:39 UTC (permalink / raw)
  Cc: guile-user

Hi,

Neil Jerram <neil@ossau.uklinux.net> writes:

>> and that the args content
>> is not explicitly documented (that is, I was not
>> able to find it) even if its content is well defined
>> in 'scm_error_scm()':
>>
>>   scm_ithrow (key,
>>         scm_list_4 (subr, message, args, data), 1);
>
> Yes, here I completely agree with you.  I've been wondering what to do
> about this for ages.  Do you think it can be solved adequately by
> precise documentation, or do we need some way of describing the
> expected throw args in code; perhaps even construct some kind of
> object model around the args with methods for getting the useful bits
> of information out?  (Use of which would be optional.)

Indeed, this exception model is not very convenient.  In some cases,
it's even hardly usable, as examplified by the `test-suite/lib.scm'
hacks (use of regexps to parse exception messages and determine their
meaning...).

Ideally, Guile should use some SRFI-3[56]-like mechanism to represent
exceptions.  Unfortunately, I don't think this could be done without
breaking compatibility.

In any case, documenting the exceptions thrown by the built-in
procedures would certainly help.

Thanks,
Ludovic.


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
@ 2006-09-01 20:10 Marco Maggi
  0 siblings, 0 replies; 15+ messages in thread
From: Marco Maggi @ 2006-09-01 20:10 UTC (permalink / raw)


"Neil Jerram" wrote:
> Out of interest, though, what changes would you like to the
> presentation?

If you are referring to  the documentation draft: I think it
is fine. If you are referring to the stack trace I posted: I
would like it  to be the same as for  a 'common' error: with
the section

> <unnamed port>: In procedure gsl-ode-evolve in expression
> (gsl-p-ode-evolve ode initial-indep-value ...):
> <unnamed port>: my error message 1 and 2

displayed at  the bottom, below  all the stack frames.  I do
not think that it is easy to do: I obtain the stack trace by
recording the stack  at the moment of error,  and then using
the  lower section  of  it  as part  of  the error  message.
Splitting a stack and appending a section to another seems a
dirty  thing (I  do not  know  how a  stack is  implemented,
though).

"Neil Jerram" wrote:

>do you think  that the way my Emacs  interface displays the
>stack is better or worse than this?
>http://www.ossau.uklinux.net/guile/debugging-demo/shot2.html

I  dunno. It has  a completely  different purpose.  Nice one
that there is a stepping debugger, though.

"Neil Jerram" wrote:
>"Marco Maggi" wrote:
>> and that the args content is not explicitly documented
>> even if its content is well defined in 'scm_error_scm()':
>>
>>   scm_ithrow (key,
>>         scm_list_4 (subr, message, args, data), 1);
>
>Yes, here I completely agree with you.

I  do not  have  enough experience  to  be authoritative  on
exception handling. :)

I want  to make clear that  the 'args' I am  referring to is
the  'args'  handed  to  the  'scm_t_catch_handler  handler'
function, parameter of  'scm_c_catch()'. This 'args' ends up
being the:

  scm_list_4 (subr, message, args, data)

list;  this  value is  exception  independent.  I want  this
'args'  created   by  'scm_error_scm()'  to   be  officially
documented  so  that  there   is  a  constraint  on  keeping
compatibility. :) I do not  think that this list needs to be
changed;  maybe a  helper function  that formats  the string
could be useful, so that one can avoid putting:

  scm_simple_format(s_port, s_message,
    (scm_is_eq(SCM_BOOL_F, s_args)? SCM_EOL : s_args));

in the code, as I have done, to build the message.


"Ludovic Courts" wrote:
>Indeed,  this exception  model is  not very  convenient.  In
>some cases,  it's even hardly usable, as  examplified by the
>`test-suite/lib.scm'   hacks  (use   of  regexps   to  parse
>exception messages and determine their meaning...).

But applications and test suites are different scenarios.

"Ludovic Courts" wrote:
>Ideally, Guile should  use some SRFI-3[56]-like mechanism to
>represent exceptions.

SRFI-35 defines  a complex value,  maybe too complex.  It is
not  clear to me  if a  fine-grained hierarchy  of exception
descriptors can really improve the quality of the code.

There   are   two   classes   of   exceptions:   logic   and
runtime. Logic  are the problems that I  should have removed
at debugging time, I do not think that it is possible to try
to recover from those.  Runtime are state synchronisations.

How can the application recover from a state synchronisation
exception?   One  aborts   the   transaction  and/or   frees
asynchronous resources allocated for the operation. Is there
a significant  number of real-world  cases in which  one can
retry the operation without aborting/freeing?

Should  it  be possible  to  do  something without  breaking
compatibility  by generalising  the 'key'  argument  and use
upon it a generalised version of 'equal?'?




--
Marco Maggi

"They say jump!, you say how high?"
Rage Against the Machine - "Bullet in the Head"



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-08-28 22:21   ` Neil Jerram
@ 2006-09-07  9:02     ` Volkan YAZICI
  2006-09-07 21:36       ` Neil Jerram
  0 siblings, 1 reply; 15+ messages in thread
From: Volkan YAZICI @ 2006-09-07  9:02 UTC (permalink / raw)
  Cc: guile-user

On Aug 28 11:21, Neil Jerram wrote:
> A common requirement is to be able to show as much useful context as
> possible when a Scheme program hits an error.  The most immediate
> information about an error is the kind of error that it is - such as
> "division by zero" - and any parameters that the code which signalled
> the error chose explicitly to provide.  This information originates with
> the `error' or `throw' call (or their C code equivalents, if the error
> is detected by C code) that signals the error, and is passed
> automatically to the handler procedure of the innermost applicable
> `catch', `lazy-catch' or `with-throw-handler' expression.

I've another situation that doesn't get executed inside a `catch' block.
For instance, I need to make some variable definitions just before
executing related code via scm_c_with_throw_handler(). The problem is,
in these definitions when an error occurs (e.g. not enough memory in
case of a scm_from_locale_string() call) I'm not able to handle it and
program exists without my permission.

In such a situation, should I try to place my whole definition related
code into a SCM function and execute in a catch scope or is there any
other way to fix this?

[If you want to take a look at the related code, see
place_scheme_args(), guile_eval_str() and handle_scm_res() functions
called inside plscheme_func_handler() function in
http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/~checkout~/plscheme/plscheme/plscheme.c?rev=1.4
URL.]


Regards.

P.S. Thanks for this paper. It's quite helpful. Now I'm planning to
     power up my buggy scm_c_with_throw_handler() code with that
     make-stack stuff.


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-09-07  9:02     ` Volkan YAZICI
@ 2006-09-07 21:36       ` Neil Jerram
  2006-09-08  6:09         ` Volkan YAZICI
  0 siblings, 1 reply; 15+ messages in thread
From: Neil Jerram @ 2006-09-07 21:36 UTC (permalink / raw)
  Cc: guile-user

Volkan YAZICI <yazicivo@ttnet.net.tr> writes:

> I've another situation that doesn't get executed inside a `catch' block.
> For instance, I need to make some variable definitions just before
> executing related code via scm_c_with_throw_handler(). The problem is,
> in these definitions when an error occurs (e.g. not enough memory in
> case of a scm_from_locale_string() call) I'm not able to handle it and
> program exists without my permission.
>
> In such a situation, should I try to place my whole definition related
> code into a SCM function and execute in a catch scope

Yes, I think that's what you need to do.  It's not too hard to do
this, is it?

> or is there any other way to fix this?

Not unless you want to change the libguile code.  The behaviour in the
case where there is no enclosing catch scope is hardcoded in
scm_ithrow (throw.c line 730):

  /* If we didn't find anything, print a message and abort the process
     right here.  If you don't want this, establish a catch-all around
     any code that might throw up. */
  if (scm_is_null (winds))
    {
      scm_handle_by_message (NULL, key, args);
      abort ();
    }


> [If you want to take a look at the related code, see
> place_scheme_args(), guile_eval_str() and handle_scm_res() functions
> called inside plscheme_func_handler() function in
> http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/~checkout~/plscheme/plscheme/plscheme.c?rev=1.4
> URL.]

It's interesting that you use separate catches for place_scheme_args,
init_spi and guile_eval_str.  Does it really make sense to go ahead
with the guile_eval_str even if one (or both) of (place_scheme_args
init_spi) failed?

My inclination would be to try to put everything inside a single
catch, if that is possible.

> P.S. Thanks for this paper. It's quite helpful. Now I'm planning to
>      power up my buggy scm_c_with_throw_handler() code with that
>      make-stack stuff.

I forgot to mention when I wrote it that you also need to be using the
debugging evaluator (otherwise make-stack doesn't do anything), but I
see that you've already got that sorted in your code.

Regards,
     Neil



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-09-01  9:39   ` Ludovic Courtès
@ 2006-09-07 22:11     ` Neil Jerram
  0 siblings, 0 replies; 15+ messages in thread
From: Neil Jerram @ 2006-09-07 22:11 UTC (permalink / raw)


ludovic.courtes@laas.fr (Ludovic Courtès) writes:

> Indeed, this exception model is not very convenient.  In some cases,
> it's even hardly usable, as examplified by the `test-suite/lib.scm'
> hacks (use of regexps to parse exception messages and determine their
> meaning...).

IMO this isn't so bad.  Using a regexp to check an exception message
makes sense (i) because the message is part of the interface, and so
worth checking, and (ii) because there will never be a distinct
exception key (or condition type, or whatever) for every possible
exception that can be thrown.

> Ideally, Guile should use some SRFI-3[56]-like mechanism to represent
> exceptions.  Unfortunately, I don't think this could be done without
> breaking compatibility.

Agreed.  I've spent some time thinking about this and haven't found a
solution yet.

> In any case, documenting the exceptions thrown by the built-in
> procedures would certainly help.

Yes, although I prefer a code solution to a documentation one, if that
is possible.

Since people seem to like SRFI-35/36, one option would be to provide a
procedure that would convert a set of throw args into the closest
matching SRFI-35/36 condition.

A developer could choose to use this in their handler procs, and then
use SRFI-35/36 procedures to interrogate the condition further.

If this is possible (which it might not be, because I'm not sure
the SRFIs define enough condition types yet), would it be an adequate
solution?

Regards,
     Neil



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: saving and restoring the error stack trace
  2006-09-07 21:36       ` Neil Jerram
@ 2006-09-08  6:09         ` Volkan YAZICI
  0 siblings, 0 replies; 15+ messages in thread
From: Volkan YAZICI @ 2006-09-08  6:09 UTC (permalink / raw)
  Cc: guile-user

On Sep 07 10:36, Neil Jerram wrote:
> Volkan YAZICI <yazicivo@ttnet.net.tr> writes:
> > I've another situation that doesn't get executed inside a `catch' block.
> > For instance, I need to make some variable definitions just before
> > executing related code via scm_c_with_throw_handler(). The problem is,
> > in these definitions when an error occurs (e.g. not enough memory in
> > case of a scm_from_locale_string() call) I'm not able to handle it and
> > program exists without my permission.
> >
> > In such a situation, should I try to place my whole definition related
> > code into a SCM function and execute in a catch scope
> 
> Yes, I think that's what you need to do.  It's not too hard to do
> this, is it?

I've created a CALL_PROC_WITH_CATCH(proc, arg) macro for this purpose. I
modified my place_scheme_args(), init_spi() and guile_eval_str()
functions into their SCM equivalents and I call these functions via
CALL_PROC_WITH_CATCH() macro. (You can find related code in the latest
revision of plscheme.c)

> > or is there any other way to fix this?
> 
> Not unless you want to change the libguile code.

No, thanks. That's not something I can wish from the PL/scheme users.

> > [If you want to take a look at the related code, see
> > place_scheme_args(), guile_eval_str() and handle_scm_res() functions
> > called inside plscheme_func_handler() function in
> > http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/~checkout~/plscheme/plscheme/plscheme.c?rev=1.4
> > URL.]
> 
> It's interesting that you use separate catches for place_scheme_args,
> init_spi and guile_eval_str.  Does it really make sense to go ahead
> with the guile_eval_str even if one (or both) of (place_scheme_args
> init_spi) failed?
>
> My inclination would be to try to put everything inside a single
> catch, if that is possible.

In here, I cannot encapsulate them into a single catch block, because I
need to make some other library calls between stages. (Yes these
mentioned library calls can go in the SCM functions but this will just
obfuscate code.) Also, the ereport() function in exception handler will
exit from the current stack (and will be catched by the outer-most
PG_TRY() block), which makes it impossible to continue to normal
continuation. (Therefore, if one of them fails, next won't get run.)

> I forgot to mention when I wrote it that you also need to be using the
> debugging evaluator (otherwise make-stack doesn't do anything), but I
> see that you've already got that sorted in your code.

I figured that out when scm_make_stack() returned SCM_BOOL_F when
debugging evaluator is not activated.


Thanks so much for your kindly help.
Regards.


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2006-09-08  6:09 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-24 19:34 saving and restoring the error stack trace Marco Maggi
2006-08-24 21:53 ` Neil Jerram
  -- strict thread matches above, loose matches on Subject: below --
2006-08-25  9:39 Marco Maggi
2006-08-27 12:53 ` Neil Jerram
2006-08-28 22:21   ` Neil Jerram
2006-09-07  9:02     ` Volkan YAZICI
2006-09-07 21:36       ` Neil Jerram
2006-09-08  6:09         ` Volkan YAZICI
2006-08-29  3:08 dsmich
2006-09-01  7:34 ` Neil Jerram
2006-08-31  6:04 Marco Maggi
2006-09-01  7:47 ` Neil Jerram
2006-09-01  9:39   ` Ludovic Courtès
2006-09-07 22:11     ` Neil Jerram
2006-09-01 20:10 Marco Maggi

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).