* 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; 16+ 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] 16+ messages in thread
* Re: saving and restoring the error stack trace
2006-08-24 19:34 Marco Maggi
@ 2006-08-24 21:53 ` Neil Jerram
0 siblings, 0 replies; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ messages in thread
* Re: saving and restoring the error stack trace
2006-08-31 6:04 saving and restoring the error stack trace Marco Maggi
@ 2006-09-01 7:47 ` Neil Jerram
2006-09-01 9:39 ` Ludovic Courtès
0 siblings, 1 reply; 16+ 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] 16+ 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; 16+ 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] 16+ messages in thread
* Re: saving and restoring the error stack trace
@ 2006-09-01 20:10 Marco Maggi
0 siblings, 0 replies; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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
2006-09-12 12:21 ` Exception handling Ludovic Courtès
0 siblings, 1 reply; 16+ 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] 16+ 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; 16+ 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] 16+ messages in thread
* Exception handling
2006-09-07 22:11 ` Neil Jerram
@ 2006-09-12 12:21 ` Ludovic Courtès
0 siblings, 0 replies; 16+ messages in thread
From: Ludovic Courtès @ 2006-09-12 12:21 UTC (permalink / raw)
Cc: guile-user
Hi,
Neil Jerram <neil@ossau.uklinux.net> writes:
> 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,
Indeed, the message conveys additional information about the exception,
and as such, it may need to be checked.
Now, I disagree that a text message, whose primary purpose is to be
human-readable --- in fact, it should even be translated depending on
the current locale, as for `strerror(3)' --- is the "right way" to
implement communication among modules (or programs, or procedures).
Such a string, in general, has to be "parsed" in order for the program
to extract its meaning (that's what the regexp does). This process is
error-prone, unreliable, and inefficient. Since Scheme provides a wide
range of types (and Guile allows the definition of additional types), it
may be wiser to use typed objects directly to communicate exception
information among different modules. (In the end, it all boils down to
arguing about typed languages compared to string-oriented languages like
Unix shells.)
> and (ii) because there will never be a distinct
> exception key (or condition type, or whatever) for every possible
> exception that can be thrown.
Well, Java successfully deals with that, as most modern languages and
implementations do. SRFI-3[56] provide a practical way to implement
that in Scheme.
Now, just because dozens of different exception types may be thrown by a
given program (or procedure) doesn't mean that its callers/users have to
handle each one of them gracefully. However, callers and users should
have the _ability_ to cope with exceptions that they know they can
recover from in a useful way.
> Yes, although I prefer a code solution to a documentation one, if that
> is possible.
Sure.
> 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?
I don't know. Do you mean something like:
(catch #t
(lambda ()
...)
(lambda exception-args
(let ((condition (guile-exception->srfi-35 exception-args)))
;; Handle CONDITION...
...)))
I think this would be quite inconvenient.
For my own procedures, I use SRFI-35 (from Guile-lib) and SRFI-34 (from
Guile core) do deal with exceptions. Unfortunately, native Guile
exceptions (like, say, `system-error') cannot be dealt with in the same
way.
Maybe SRFI-34 is the place where a transparent compatibility layer from
Guile's native key+args to SRFI-3[56] exceptions could be implemented?
For instance, before invoking the handler, it checks whether the "key"
argument of the exception is `srfi-34' or something else, and if it's
something else, it tries to convert it to the relevant condition type.
What do you think?
Thanks,
Ludovic.
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2006-09-12 12:21 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-31 6:04 saving and restoring the error stack trace 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-12 12:21 ` Exception handling Ludovic Courtès
-- strict thread matches above, loose matches on Subject: below --
2006-09-01 20:10 saving and restoring the error stack trace Marco Maggi
2006-08-29 3:08 dsmich
2006-09-01 7:34 ` Neil Jerram
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-24 19:34 Marco Maggi
2006-08-24 21:53 ` Neil Jerram
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).