This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

debug information

Help for those learning Tcl or writing their own scripts.
Post Reply
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

debug information

Post by arfer »

I have a script debug.tcl (published to egghelp) which, rather than the minimal error messages that show in the partyline, gives a full trace on any errors that occur using the variable errorInfo. This can be very useful if, in the script causing the error, a proc calls a proc that calls a proc etc that generates the error.

Whilst the script performs as expected, there is one, sometimes annoying, aspect of its performance that I would like to change. This concerns errors generated from a catch statement. An error trapped by a catch statement does not show in the partyline but yet does write to errorInfo, as a consequence my script picks it up and generates an output.

I am thinking therefore that there is a discernable difference between such errors that causes the normal partyline message to be nullified in the case of properly caught errors. Perhaps something within tclvars. I would ideally like to employ a user configured variable within my script to give the choice of showing caught errors or not.

Any thoughts on how to identify the difference between a genuine error and one trapped by a catch statement would be appreciated.
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

A solution would be to add some custom word to errorInfo in case the error is caught, for example:

Code: Select all

if {[catch {<code-here>} error]} {
 set errorInfo "CAUGHT: $error"
}
So in your script you parse errorInfo to see if it contains the keyword CAUGHT, otherwise it's an uncaught-error.

It's not a "good" solution of course since you'll have to edit other scripts instead of just debug.tcl to do it.

Edit: Or you can simply set errorInfo "" in case the error is caught (instead of adding a keyword).
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

Another solution is to override Tcl's [catch] command with your own, try this:

Code: Select all

rename catch _catch

proc catch arg {
 if {[_catch $arg]} {
  set errorInfo ""
  return 1
 }
 return 0
}
Not tested.

Edit: Yes nml375 you're right about the number of arguments for [catch], so let's consider the above as just an example. In case such an override should be made, check catch man-page.
Last edited by Sir_Fz on Sat Feb 09, 2008 3:15 pm, edited 1 time in total.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Since the errorInfo variable is trace'd, this would still trigger on caught errors, and in the case where you (re)set errorInfo, would cause double-triggering.

Also, Sir_Fz, you've got the number of arguments for catch wrong...

All in all, it's an interresting approach. Unfortunately, you'll run into these issues with scripts that actually do their own error-handling (as they should) rather than just blindly ignoring them and hoping for the best.


One approach however, might be to change from tracing errorInfo, into actually rewriting loaded scripts on the fly, making them call a function to report the error:
That is, change things like this (and yes, this is intentionally written VERY poorly, don't ever code something like this, EVER!!!):

Code: Select all

proc myUnsafeProc {nick host hand chan text} {
  puthelp "PRIVMSG $chan :[lindex $text 0]"
  return 0
}
Into something like this (still bad code, but atleast it has some error handling):

Code: Select all

proc myUnsafeProc {nick host hand chan text} {
  if {[catch {
    puthelp "PRIVMSG $chan :[lindex $text 0]"
    return 0
  } error]} {
    reportError $error $::errorInfo $::errorCode
    error $error $::errorInfo $::errorCode
  } else {
    return $error
  }
}
This should not interfere with most scripts that do their own error-handling, although it might be a good idea to implement a feature to "whitelist" proc's that don't like being mangled... Also, this will still generate the error in question, so scripts that rely on subcalls generating errors in certain condition should'nt be too upset.

Basic approach would be something like this:

Code: Select all

foreach process [info proc] {
  proc $process [info args $process] "
  if {\[catch {
  [info body $process]
  } error \]} {
    reportError \$error \$::errorInfo \$::errorCode
    error \$error \$::errorInfo \$::errorCode
  } else {
    return \$error
  }"
}
Problem here however, is that you'd have to make sure this piece of code is not executed until all other scripts have been loaded and created all procs necessary.
NML_375
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

Many thanks for your input. I'll give it some thought. Doubtful however that any changes to my other scripts proffer a generic solution, since my intention has been to make the script publicly available for users to find and trace errors on any script from any author they might have loaded.

Let me rephrase the question though. If a caught error writes to errorInfo then how is it prevented from ouputting to the partyline? Perhaps tcl errors that are output normally to the partyline are via something other than changes to errorInfo?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

The error-reporting in eggdrop does not rely on tracing errorInfo or such. Instead, each mechanism that invokes tcl-code checks the return-status, and if an error condition is present, sends this to the MISC logqueue.

The only option left would be to rewrite eggdrop's source, namely the error reporting mechanism, and make it dump all the info. Have a look at the trigger_bind() function in tclhash.c for an example on how the error logging is done.
NML_375
Post Reply