View previous topic :: View next topic |
Author |
Message |
sKy Op

Joined: 14 Apr 2005 Posts: 194 Location: Germany
|
Posted: Mon Aug 15, 2005 6:39 am Post subject: searching for errors/bugs in a script |
|
|
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 |
|
 |
sKy Op

Joined: 14 Apr 2005 Posts: 194 Location: Germany
|
Posted: Mon Aug 15, 2005 6:50 am Post subject: |
|
|
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 .
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 |
|
 |
demond Revered One

Joined: 12 Jun 2004 Posts: 3073 Location: San Francisco, CA
|
Posted: Wed Aug 17, 2005 1:38 am Post subject: |
|
|
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 |
|
 |
rosc2112 Revered One

Joined: 19 Feb 2006 Posts: 1454 Location: Northeast Pennsylvania
|
Posted: Sun Jun 11, 2006 12:08 pm Post subject: no-crash script loader |
|
|
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  |
|
Back to top |
|
 |
|