egghelp.org community Forum Index
[ egghelp.org home | forum home ]
egghelp.org community
Discussion of eggdrop bots, shell accounts and tcl scripts.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

searching for errors/bugs in a script

 
Post new topic   Reply to topic    egghelp.org community Forum Index -> Tcl FAQ
View previous topic :: View next topic  
Author Message
sKy
Op


Joined: 14 Apr 2005
Posts: 194
Location: Germany

PostPosted: Mon Aug 15, 2005 6:39 am    Post subject: searching for errors/bugs in a script Reply with quote

Here are some tips which should help you to find errors or bugs in a script.
Firstly i suggest to read this thread: http://forum.egghelp.org/viewtopic.php?t=10215

Questions like "How the bot won`t do this or this" won`t really help you or others to find out why. The better way may be to try to understand how tcl works.

The following short proc will putlog the procname and the variables of the atual proc.
Quote:
name-of-proc args1 ?arg arg ...?

Code:
proc logCaller {} {
   set r [catch {info level [expr [info level] - 1]} e]
   if {$r} {
       putlog "Called directly by the interpreter (e.g.: .tcl on the partyline)."
   } {
      putlog "Called by ${e}."
   }
}

or you can use: putlog "procname $var $var2 ..."
Always, if something won`t work and you have no idea why then you should use putlog to show you the exact point of the problem and the content of your variables, returncodes etc.

--
Beware of adding scripts to your config and to type .rehash without testing them. If there are unbalanced barces this will crash your bot which means you have to restart him. To load a script on the save way you have to use the source command in combination with catch. Something like that should be useful:
Code:

# .s scriptname
# not .s scriptname.tcl
bind dcc n|- s script:load
proc script:load { handle idx text } {
   if { [catch { uplevel #0 [list source scripts/$text.tcl] } error] } {
      putlog "0,4Error while loading $text -- Errormsg: $error"
      putlog "script: $text -- ::errorInfo: $::errorInfo"
      return
   }
   putlog "script: $text -- loaded without error."
   return
}

That`s how i suggest you should scripts if you are not 100% sure if there is no error inside.


Last edited by sKy on Mon Aug 15, 2005 7:01 am; edited 1 time in total
Back to top
View user's profile Send private message
sKy
Op


Joined: 14 Apr 2005
Posts: 194
Location: Germany

PostPosted: Mon Aug 15, 2005 6:50 am    Post subject: Reply with quote

If you have big scripts and many procs which will call each other and you don`t know really which proc got called by another one you can use this.
Code:
# strace (original by Elven http://tclhelp.net/forum/viewtopic.php?t=96)
# usage:
# putlog [strace]
proc strace { {args ""} } {
   if { [info level] == 1 } {
      return "strace: got called directly by the interpreter (e.g.: .tcl on the partyline)."
   }
       set ret {}
       set r [catch {expr [info level] - 1} l]
       if {$r} { return {""} }
       while {$l > -1} {
               incr l -1
               lappend ret [info level $l]
       }
   set ret [lremove $ret [lindex $ret [expr [llength $ret] - 2]]]
   set last [lrange $ret end end]
   set ret [lreplace $ret end end]
   eval lappend last $ret
   set while_protection 0
   while { [llength $last] != 0 } {
      set x [lindex $last end]
      set last [lremove $last $x]
      if { $x == "" } {
         break
      }
      set x [lindex [split $x] 0]
      lappend newlist $x
      incr while_protection
      if { $while_protection > 100 } {
         putlog "strace: breaking loop, to many executions (>100)."
         break
      }
   }
   set newlist [join [split $newlist] " --> "]
   return $newlist
}


Examaple for what this proc can be used for:
Code:
proc test_a args { test_b 2 2 2 }
proc test_b args { test_c 3 3 3 }
proc test_c args { test_d 4 4 4 }
proc test_d args { test_e 5 5 5 }
proc test_e args { putlog "procname: test_e: strace: [strace]" }

type: .tcl test_e

This will show you which proc got called first, which second, etc...

--

Quote:
Tcl error: invalid command name "s"

Yeah nice :/ You have many procs and don`t know which script cause this error... How can you find more fast? (http://www.tcl.tk/man/tcl8.5/TclCmd/unknown.htm)

Code:
if { [info command unknown_new] == "" } {
   rename unknown unknown_new
}

proc unknown { args } {
   set command [join [lrange [split $args] 0 0]]
   set arg [join [lrange [split $args] 1 end]]
   putlog "WARNING: unknown command: $command (arguments: $arg) | Lastbind: $::lastbind"
   uplevel #1 [list unknown_new $args]
}


Another nice tcl feature is the errorInfo varibale. I wonder that so less people know it.

Code:
bind dcc n|- e dcc:errorinfo
proc dcc:errorinfo { handle idx text } {
   putlog $::lastbind
   putlog $::errorInfo
}


This will show a multi line traceback to the last error. If you read this you will know what you have to do to prevent this error.
The ugly point is, errorInfo shows always the last error. So, if you use catch and a error has been caused it will show that error last, so be fast Wink.

thom\mey showed me a nice way to handle that.
Code:

trace add variable ::errorInfo write logerr
proc logerr { args } {
  if { [set utm [utimerexists errorlog]] != "" } { return }
  utimer 1 errorlog
}
proc errorlog { } {
  set fs [open errorlog.txt a]
  regsub -all -- {\n|\s+} $::errorInfo { } error
  putlog $::errorInfo
  puts $fs "\n"
  puts $fs "[clock format [clock seconds] -format "%d/%m/%y@%H:%M.%S>"] : $::errorInfo"
  close $fs
}

Well, in some case this will create a big error errorlog.txt. I don`t know... Do you want this? But the putlog works nice for me.
Back to top
View user's profile Send private message
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Wed Aug 17, 2005 1:38 am    Post subject: Reply with quote

small correction: the trace command handler is invoked with 3 arguments, not 1; so [logger] actually becomes:
Code:

proc logger {name1 name2 op} {
   # stuff
}
Back to top
View user's profile Send private message Visit poster's website
rosc2112
Revered One


Joined: 19 Feb 2006
Posts: 1454
Location: Northeast Pennsylvania

PostPosted: Sun Jun 11, 2006 12:08 pm    Post subject: no-crash script loader Reply with quote

Just thought I'd post my little script that I created after reading the post by sky. This allows loading any script without it crashing the bot (wish I had found this sooner! <g>) This is how the script is loaded in eggdrop.conf:

##### SCRIPTS #####
source scripts/scripts.txt

and then the scripts.txt file uses:
Code:

set error ""
foreach script {
alltools.tcl
cmd_resolve.tcl
whatever-script-one-per-line.tcl
} {
catch {source scripts/$script} error
if {$error != ""} {putcmdlog "\002SCRIPT ERROR\002:$script\: $::errorInfo"}
}


Never have another bot crash from a script error on load Smile
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    egghelp.org community Forum Index -> Tcl FAQ All times are GMT - 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Forum hosting provided by Reverse.net

Powered by phpBB © 2001, 2005 phpBB Group
subGreen style by ktauber