Catch "Tcl Interpreter Error" - tcl

Is there any way to catch the global "Tcl Interpreter Error"? For example I would like to automatically store in some file the message that follows.

The core command for trapping any kind of error thrown by Tcl is catch. It takes at least one argument, a script to evaluate, and returns the result code from evaluating that script. The result code is 1 when an error occurs, 0 when there was no error, and a bunch of other things in other cases (indicating other types of usually-non-error exception). The catch also takes an optional argument that names a variable into which to write the result of evaluating the script or the error message. The global variable errorInfo will contain the stack trace in the case of an error (or from 8.5 onwards you can get the interpreter state dictionary with a further variable name passed to catch).
To trap an error in some script “foo.tcl”, you would use code like this:
if {[catch {source foo.tcl} msg]} {
puts "I got an error: $msg"
puts "The stack trace was this:\n$errorInfo"
}
It's up to you to work out how to write that out to a file if you want. (I use this technique with an outer script that implements a carefully tested error trap and which loads an inner script that does the real work. I find it works well. Or you can call procedures in that “caught” script. Up to you really; Tcl should make all errors trappable, and there are very few conditions which slip through.)
The other route that errors can be reported is via bgerror, which is called to handle errors that occur during event processing. It's a procedure you can write your own version of; it will be given a single argument when called that is the error message, and will have the global errorInfo set correctly when called:
proc bgerror {msg} {
global errorInfo
puts "I got an error in an event: $msg"
puts "The stack trace was this:\n$errorInfo"
}
If there is no implementation of bgerror defined, the stack trace is just written to the stderr channel. If you're using the Tk package, an implementation of bgerror is provided which pops up a dialog box describing the problem.

Try the bgerror or interp bgerror commands.
Read the bgerror documentation, it has a simple example.

Related

catching classes that do not inherit from BaseException is not allowed

I'm making a custom plugin to query a database for user info to aide customer support. My backend is slack.
Everytime I start the bot command I'm greeted with:
Computer says nooo. See logs for details:
catching classes that do not inherit from BaseException is not allowed
I'm not sure if this is warning me that I'm attempting to catch an exception that isn't a BaseClass in my code or if an unknown exception was raised and caught elsewhere outside of my plugin.
To debug I tried:
try:
do_the_thing()
except (TypeError, ValueError) as e:
return('Something went wrong.')
I also tried:
try:
do_the_thing()
except Exception as e:
return('Something went wrong.')
And I still get the errbot admonition. Note that the command still runs and does the right thing where there is no exception raised by do_the_thing().
It means that:
Somewhere in your code you have an except ... statement where the exception ... (or one of the exceptions in the sequence ...) is not a subclass of BaseException, and
An exception is being thrown that is caught by that except ... statement.
The TypeError can be raised only when an exception is actually thrown because the names you give to except ... must be evaluated for their current values at that time; just because TypeError referenced a particular class at one point in the program's execution doesn't mean it won't be changed later to reference another object (though that would be admittedly perverse).
The Python interpreter should be giving you a full traceback of the exception; the first thing you need to do is find this. It could be occurring in one of two situations. (This is for single-threaded programs; I'm assuming your program is not multithreaded.)
During the execution of your program, in which case the program will be terminated by the exception, or
During finalization of objects (in their __del__(self) functions) in which case the error will be printed to stderr.
In both cases there should be a stack trace, not just the error message; I've confirmed that at least on Python ≥3.4 a stack trace is printed out for case 2.
You then need to follow this stack trace to see where the problem lies. Remember that the names you give to except ... are variables (even things like TypeError) that can be reassigned, so that you could conceivably be dealing with a (perverse) situation like:
TypeError = False
try:
...
except TypeError:
...
But more likely it will be something obvious such as:
class MyException: # Doesn't inherit from Exception
...
try:
...
except MyException:
...
There is one special case you need to be aware of: if you are seeing messages to stderr (case "2. During finalization," above) printed out as your program exits that means that the exception was thrown during cleanup as the interpreter shuts down, where random variables throughout the program may have already been set to None as part of the cleanup process. But in this case your program should still exit successfully.

How long is a line after a readline(fh, line) call?

I have written a JSON parser in VHDL. The parser core uses two nested loops:
1. loop over all lines until EOF
2. loop over every char until line of end
For clearance: Its not a hardware parser. the parser used to read synthesis settings at synthesis time to configure instantiated entities like a baudrate in a UART module.)
The inner loop looks like this: loopj : for j in CurrentLine.all'range loop
Source: JSON.pkg.vhdl
This code works in XST 14.7, iSim 14.7 and GHDL, but not in Vivado. Vivado does not support .all. The error message is this one:
ERROR: [Synth 8-27] access type dereference not supported [D:/git/GitHub/JSON-for-VHDL/vhdl/JSON.pkg.vhdl:293]
Updated code, due to the hint from kraigher:
#Paebbles Have you tried foo'range instead of foo.all'range? I think I remember that it should implicitly work. - kraigher
I tried it before, but got an error. Maybe this error was related to another one. Now its working. So my current loopj line looks like this:
loopj : for j in CurrentLine'range loop
This line works fine in XST, iSim, GHDL and QuestaSim, but Vivado still has problems:
INFO: [Synth 8-638] synthesizing module 'Boards2' [.../Boards2.vhdl:16]
ERROR: [Synth 8-278] expression 0 out of range [.../JSON.pkg.vhdl:293]
ERROR: [Synth 8-421] mismatched array sizes in rhs and lhs of assignment [.../Boards2.vhdl:20]
ERROR: [Synth 8-285] failed synthesizing module 'Boards2' [.../Boards2.vhdl:16]
How can a expression be out of range? This message is very strange.
Is there another way to get a range for a loop, depending on how long the current line is?

Let Last exceptions from Last powershell execution only

I need to print some exception onto screen/Log in file.
Is there a way to get all exceptions that resulted from last script execution only ?
Consider this as an example :
I open a powershell window
I exceute abc.ps1 , it throws some error.
I execute now xyz.ps1 which throws more than one exception. Now I want to log all exception from xyz.ps1 only.
If i use $error[0], I get only last exception . I need other exceptions that were thrown by xyz.ps1 as well
I think I have come up with the way to do this. If you inspect the properties of $error[0] with Get-Member cmdlet ($error[0] | Get-Member) you should notice a property called ScriptStackTrace. This property tells us if the error was raised from a script or from console. With the following code I managed to achieve what you ask for:
for ($i=0;$i -lt $error.Count; $i++)
{ if ($Error[$i].ScriptStackTrace -match "xyz.ps1")
{ $error[$i] | out-file -Append "ErrorsScriptXYZ.txt" } }
If you intend to use the script in a callable way, add this as the last line of execution. Note that it will not catch terminating errors that could occur before the script operates. Explore the Get-Member cmdlet for more properties that you wish to manipulate on. Note that this will only search for errors in the current variable session, as the errors are gone on the next startup.

Erlang uncatchable exception

I have the following code in Erlang, in which I'm mecking an nonexistent module.
In some versions of Erlang/meck this generates an exception that seems uncatchable.
Anyone knows if there is an "uncatchable exception" feature in Erlang ?
try
meck:new(i_dont_exist),
io:format("No exception in this version of Erlang ... :( "),
no_problems
catch
exit:_ -> exit;
error:_ -> error;
throw:_ -> throw;
_:_ -> what_class_is_it
after
io.format("in the after~n")
end.
When I execute this code this is what I get (notice that not even the "after" clause is being executed so it looks more like a bug to me):
** exception exit: {undefined_module,i_dont_exist}
in function meck_proc:resolve_can_expect/3 (src/meck_proc.erl, line 402)
in call from meck_proc:init/1 (src/meck_proc.erl, line 194)
in call from gen_server:init_it/6 (gen_server.erl, line 304)
in call from proc_lib:init_p_do_apply/3 (proc_lib.erl, line 227)
I have also tried with the "catch" expression with the same result:
> catch meck:new(i_dont_exist).
** exception exit: {undefined_module,i_dont_exist}
in function meck_proc:resolve_can_expect/3 (src/meck_proc.erl, line 402)
in call from meck_proc:init/1 (src/meck_proc.erl, line 194)
in call from gen_server:init_it/6 (gen_server.erl, line 304)
in call from proc_lib:init_p_do_apply/3 (proc_lib.erl, line 227)
What's happening here is that meck:new spawns a new process (a gen_server process using the meck_proc callback module), and that process exits with the undefined_module error. (You can get it not to do that by passing the non_strict option to meck:new.) This new process is linked to the calling process, which means that an exit signal will be sent to the calling process, and the calling process will exit as well, without being able to catch the signal.
You can avoid that by making your calling process trap exits:
process_flag(trap_exit, true)
which will turn the exit signal into a message that you can receive; see the manual for more details. However, as a general rule you should avoid trapping exits, as it makes error handling more complicated (as opposed to the default "crash, restart").

BeepBeep and ErlyDB integration issue

Further to my adventures with Erlang and ErlyDB. I am attempting to get ErlyDB working with BeepBeep
My ErlyDB setup works correctly when run outside of the BeepBeep environment (see Debugging ErlyDB and MySQL). I have basically take the working code and attempted to get it running inside BeepBeep.
I have the following code in my controller:
handle_request("index",[]) ->
erlydb:start(mysql,Database),
erlydb:code_gen(["thing.erl"],mysql),
NewThing = thing:new_with([{name, "name"},{value, "value"}]),
thing:save(NewThing),
{render,"home/index.html",[{data,"Hello World!"}]};
When I call the URL, the response outputs "Server Error".
There is no other error or exception information reported.
I have tried wrapping the call in try/catch to see if there is an underlying error - there is definitely an exception at the call to thing:new_with(), but no further information is available.
The stacktrace reports:
{thing,new,[["name","value"]]}
{home_controller,create,1}
{home_controller,handle_request,3}
{beepbeep,process_request,4}
{test_web,loop,1}
{mochiweb_http,headers,4}
{proc_lib,init_p_do_apply,3}
Use pattern matching to assert that things work up to the call to thing:new/1:
ok = erlydb:start(mysql,Database),
ok = erlydb:code_gen(["thing.erl"],mysql),
You include only the stack trace, look at the exception message as well. I suspect that the error is that you get an 'undef' exception. But check that it is so. The first line in the stack trace indicates that it is a problem with calling thing:new/1 with ["name", "value"] as argument.
It is slightly odd that you show one clause of handle_request that is not calling home_controller:create/1 as per {home_controller,create,1} in the stack-trace. What do the other clauses in your handle_request/2 function look like?