Discussion:
Show argument values in bgerror
(too old to reply)
alexandru
2024-09-17 21:31:25 UTC
Permalink
I have this ::bgerror function to help debug errors in program flow:

proc ::bgerror {message} {
global errorInfo
puts "*** START OF ERROR MESSAGE ***\n$message\n$errorInfo\n*** END OF
ERROR MESSAGE ***"
}

The issue is, that the errorInfo does not show the values of the
arguments of called procedures in the stack.
Thus it's often not clear which arguments lead the the error.
Is there a trick how to show the values with which the procedures were
called in the stack prior to the error?

Many thanks
Alexandru
et99
2024-09-18 02:32:55 UTC
Permalink
Post by alexandru
proc ::bgerror {message} {
 global errorInfo
 puts "*** START OF ERROR MESSAGE ***\n$message\n$errorInfo\n*** END OF
ERROR MESSAGE ***"
}
The issue is, that the errorInfo does not show the values of the
arguments of called procedures in the stack.
Thus it's often not clear which arguments lead the the error.
Is there a trick how to show the values with which the procedures were
called in the stack prior to the error?
Many thanks
Alexandru
Here's some test code I cobbled together, I think there may be something here that does what you want. The "info level [info level]" might be just what you need, if issued at the proper uplevel. Note, the outer info has 2 args, the inner info only 1 and that's intentional. You likely would iterate on uplevel's and toss ones that give an error.

console show
proc foo {} {foo2 11 22 33}

proc foo2 {a b c} {set x 1; set y 2; foo3}

proc foo3 {} {
set level [info frame]
puts "level= |$level| "
set vars [ \
uplevel 1 {
set _vars [info vars]
puts "_vars= |$_vars| level= [info frame] args= [info level [info level]]"
foreach _var $_vars {
puts " _var= |$_var| "
lappend _varsx "$_var = [set $_var]"
}
set _varsx
}
]
puts "vars= |$vars| "
puts [join $vars \n]
}
if [catch {
foo
} err_code] {
puts $err_code
}

output:

level= |9|
_vars= |a b c x y| level= 10 args= foo2 11 22 33
_var= |a|
_var= |b|
_var= |c|
_var= |x|
_var= |y|
vars= |{a = 11} {b = 22} {c = 33} {x = 1} {y = 2}|
a = 11
b = 22
c = 33
x = 1
y = 2
alexandru
2024-09-18 10:24:23 UTC
Permalink
Wow, thanks for the input. I'll try to use it to solve the problem.

Regards
Alexandru
Harald Oehlmann
2024-09-18 07:14:34 UTC
Permalink
Post by alexandru
proc ::bgerror {message} {
 global errorInfo
 puts "*** START OF ERROR MESSAGE ***\n$message\n$errorInfo\n*** END OF
ERROR MESSAGE ***"
}
The issue is, that the errorInfo does not show the values of the
arguments of called procedures in the stack.
Thus it's often not clear which arguments lead the the error.
Is there a trick how to show the values with which the procedures were
called in the stack prior to the error?
Many thanks
Alexandru
info errorstack ?

% proc e {v} {incr v}
% e a
expected integer but got "a"
% set errorInfo
expected integer but got "a"
while executing
"incr v"
(procedure "e" line 1)
invoked from within
"e a"
% info errorstack
INNER incrScalar1Imm CALL {e a}

Harald
alexandru
2024-09-18 10:23:34 UTC
Permalink
Hi Harald,

I'll use your example with small changes to explain the issue:

proc e {v} {incr v}
set x "a"
e $x
puts $errorInfo

will output:

expected integer but got "a"
while executing
"incr v"
(procedure "e" line 1)
invoked from within
"e $x"
(file "C:/arbeit/MESHPARTS-Software/test3.tcl" line 4)
invoked from within
"source -encoding utf-8 C:/arbeit/MESHPARTS-Software/test3.tcl"

As you can see, upstream procedure calls are printed with dollar sign,
unevaluated values.
In more complex nested calls, the information about arguments gets lost
and errorInfo does not show which argument values were used.
Harald Oehlmann
2024-09-18 11:50:21 UTC
Permalink
Post by alexandru
As you can see, upstream procedure calls are printed with dollar sign,
unevaluated values.
In more complex nested calls, the information about arguments gets lost
and errorInfo does not show which argument values were used.
That is exactly what "info errorstack" is about.
See, that the "a" is substituted as argument "v".
It only works for items putting something on the call stack, so, it will
not help for your eval example. But you get the values supplied to all
procedures...

Take care,
Harald
alexandru
2024-09-18 13:21:12 UTC
Permalink
Here is the errorInfo of a true life situation.
The value of "val" is not output.
Maybe it should and it was intended so, but it's not.
So it's a bug then...

*** ERROR ***
Time: Monday, das 16 von September, 2024, um 13:24:37
integer value too large to represent
while executing
"expr {round($val*(10.0**($decimals+3)))/(10.0**$decimals)}"
(procedure "NumberReadmm" line 5)
invoked from within
"NumberReadmm $contact_offset 6"
(procedure "ContactOffsetFormat" line 7)
invoked from within
"ContactOffsetFormat $contact_offset_min"
(procedure "UIRelationApplyContactOffset" line 45)
invoked from within
"UIRelationApplyContactOffset %W"
invoked from within
".valid.notebook.f5.buttons.b2 invoke "
invoked from within
".valid.notebook.f5.buttons.b2 instate !disabled {
valid.notebook.f5.buttons.b2 invoke } "
invoked from within
".valid.notebook.f5.buttons.b2 instate pressed {
valid.notebook.f5.buttons.b2 state !pressed;
valid.notebook.f5.buttons.b2 instate !disabled { .valid..."
(command bound to event)
Harald Oehlmann
2024-09-18 14:54:35 UTC
Permalink
Post by alexandru
Here is the errorInfo of a true life situation.
The value of "val" is not output.
Maybe it should and it was intended so, but it's not.
So it's a bug then...
Alexandru,
it is not a bug. I don't speak about $::errorInfo, but "info
errorstack", or the "-errorstack" component of the error dict.

Here is a complete example as proposed by Don (thanks !):

proc bgerrorhandler {message errordict} {
puts "*** START OF ERROR MESSAGE ***"
puts $message
puts "*** ERROR INFO ***"
puts [dict get $errordict -errorinfo]
puts "*** ERROR STACK ***"
foreach {call arg} [dict get $errordict -errorstack] {
puts "$call:$arg"
}
puts "*** END OF ERROR MESSAGE ***"
}
interp bgerror "" bgerrorhandler
proc e1 {v} {incr v}
proc e2 {v} {e1 $v}
after idle {e2 a}

This gives the output:
*** START OF ERROR MESSAGE ***
expected integer but got "a"
*** ERROR INFO ***
expected integer but got "a"
while executing
"incr v"
(procedure "e1" line 1)
invoked from within
"e1 $v"
(procedure "e2" line 1)
invoked from within
"e2 a"
("after" script)
*** ERROR STACK ***
INNER:incrScalar1Imm
CALL:e1 a
CALL:e2 a
*** END OF ERROR MESSAGE ***

So, the error info has the variable names ($v in this case), while the
error stack has the values ("a" in this case).

Might this suit your needs ?

Take care,
Harald
alexandru
2024-09-20 12:04:38 UTC
Permalink
Thanks Harald,

This code perfectly solves my problem.

Best regards
Alexandru
rene
2024-09-24 05:54:14 UTC
Permalink
Hello Harald,

where did you find the second "errordict" argument of the new bgerror
proc. In the bgerror documentation is only the "message" argument.
May be a documentation error?

Regards
Rene

PS. I will try to answer the oo question later this week.
Harald Oehlmann
2024-10-13 11:03:11 UTC
Permalink
Post by rene
Hello Harald,
where did you find the second "errordict" argument of the new bgerror
proc. In the bgerror documentation is only the "message" argument.
May be a documentation error?
No, this is correct. The bgerror procedure is the old fashion and is
obsolete. Use the interp bgerror described here:
https://www.tcl-lang.org/man/tcl8.6/TclCmd/interp.htm#M55

The two arguments are described in the subsection "Background error
handling"
Post by rene
PS. I will try to answer the oo question later this week.
Great !

Thank you,
Harald

Don Porter
2024-09-18 13:46:54 UTC
Permalink
The [interp bgerror] command has been available since the release
of Tcl 8.5.0 in 2007. No one should be continuing to struggle against
the deficits of the [bgerror] facility.
Post by alexandru
proc ::bgerror {message} {
 global errorInfo
 puts "*** START OF ERROR MESSAGE ***\n$message\n$errorInfo\n*** END OF
ERROR MESSAGE ***"
}
The issue is, that the errorInfo does not show the values of the
arguments of called procedures in the stack.
Thus it's often not clear which arguments lead the the error.
Is there a trick how to show the values with which the procedures were
called in the stack prior to the error?
Many thanks
Alexandru
--
| Don Porter Applied and Computational Mathematics Division |
| ***@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|
Loading...