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 

[SOLVED] catch errors, dont make eggy die
Goto page 1, 2  Next
 
Post new topic   Reply to topic    egghelp.org community Forum Index -> Scripting Help
View previous topic :: View next topic  
Author Message
raider2k
Op


Joined: 01 Jan 2008
Posts: 140

PostPosted: Sun Mar 21, 2010 2:37 pm    Post subject: [SOLVED] catch errors, dont make eggy die Reply with quote

hi folks ^^

this time im looking for a way to catch errors that usually crash the eggy WITHOUT crashing it. ive seen this somewhere once, i tried it already with

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"}
}


from http://forum.egghelp.org/viewtopic.php?p=63899#63899

and with

Code:

catch {unbind raw - PRIVMSG *raw:irc:msg}
catch {unbind raw - PRIVMSG *raw:PRIVMSG}


from http://forum.egghelp.org/viewtopic.php?t=12944&highlight=catch

the first one only put out one line of the error, tried to work it around with split "\n" and/or foreach but no go so far. the second didnt do anything at all.

so im not sure if im missing anything or just did it the wrong way


Last edited by raider2k on Mon Mar 22, 2010 2:08 am; edited 1 time in total
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Sun Mar 21, 2010 3:03 pm    Post subject: Reply with quote

That script is not quite properly written; I'd rather suggest something along these lines:
Code:
proc loadsafe {scripts} {
  foreach script $scripts {
    if {[catch [list uplevel #0 [list source $script]] err]} {
      putcmdlog "Error loading $script: $err"
      foreach line [split $::errorInfo "\n"] {
        putcmdlog $line
      }
    }
  }
}

loadsafe [list scripts/alltools.tcl scripts/cmd_resolve.tcl scripts/and_so_on.tcl]

Keep in mind that the loadsafe proc expects a list of scripts, even if you only load one script. If you fancy having one script per line, then this should work just fine:
Code:
...
loadsafe [list scripts/alltools.tcl \
  scripts/cmd_resolve.tcl \
  scripts/and_so_on.tcl]



The second piece of code you've linked is only supposed to safely remove two raw bindings from your eggdrop.

Edit: script is now source'd at the global level, by suggestion from user.
_________________
NML_375, idling at #eggdrop@IrcNET


Last edited by nml375 on Wed Mar 24, 2010 11:13 am; edited 1 time in total
Back to top
View user's profile Send private message
raider2k
Op


Joined: 01 Jan 2008
Posts: 140

PostPosted: Mon Mar 22, 2010 1:27 am    Post subject: Reply with quote

both are just examples, aka the original code from that forum thread, of course i modified it to my needs Wink

im wondering a bit about your examples - where is $scripts in foreach script $scripts coming from? and where is $::errorInfo coming from? im not able to follow the pointer from one to the other in that case, sorry :> (i see that $::errorInfo is also in the original thread, didnt pay much attention to it - is it some kind of global var?)
Back to top
View user's profile Send private message
raider2k
Op


Joined: 01 Jan 2008
Posts: 140

PostPosted: Mon Mar 22, 2010 2:07 am    Post subject: Reply with quote

Code:

proc loadscript { scripts } {
        foreach script $scripts {
                if { [catch { source $script } err] } {
                        putlog "ERROR LOADING $script: $err"
                        foreach x [split $::errorInfo "\n"] {
                              putlog "$x"
             
                        }
                }
        }
}

set scripts {
scripts/something.tcl
scripts/debug.tcl
scripts/externalscript.tcl
scripts/sql.tcl
}

loadscript $scripts


i did it like this and it works like a charm, dont want the scripts i like to load to be in one line, like to have it organized and structured and the other code you posted with " \ " at the end didnt really work out, regardless of how i turned and turned it, didnt work - so i did it differently and it works, tested and works Smile

thx again nml ^^


Last edited by raider2k on Mon Mar 22, 2010 12:22 pm; edited 1 time in total
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Mon Mar 22, 2010 11:35 am    Post subject: Reply with quote

First, your questions..

I placed my code in a proc I called "loadsafe", that takes one parameter (the list of scripts). So $scripts comes from the proc argument list..

Next, $::errorInfo:
This is a global variable (see the namespace operator :Smile, that contains details regarding the latest error that occured. Since I use a full namespace path when accessing the variable, I don't have to use the global command.

Regarding your code, I would recommend that you do not build your list of scripts that way. You'll get away with it most of the times, but if your filenames contains characters such as { or }, you might be up for a nasty surprise (plus it's really bad coding practise that we see all too often).

Regarding your issues with the list command and using backslash (\), did you place a newline immediately after the backslash? It is solely used to escape the newline, so there cannot be any spaces or other characters between the \ and the newline.
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
raider2k
Op


Joined: 01 Jan 2008
Posts: 140

PostPosted: Mon Mar 22, 2010 12:22 pm    Post subject: Reply with quote

yup, this is true, figured where scripts comes from when i copied and modified it to my needs ^^

yup, namespace global var, got that, just wasnt really sure ^^

im wondering a bit whats so wrong about my code, having escapable character in FILENAMES isnt going to happen at all, i NEVER used and never will use special chars in a filename, is there anything i need to be aware of or is it only characters which need to be escape in case of?
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Mon Mar 22, 2010 1:09 pm    Post subject: Reply with quote

The problem is that tcl lists are very delicate, while alot of coders/users think having one item per line automatically makes the string a list. The tcl interpreter will try it's best to parse the string as a list when using foreach, lindex, etc. but every now and then the string is too poorly formatted to make sense of.
In your case, you'll most likely get away with it, as I said in my previous post. But since this forum is alot about helping people code (better), I like to point out issues like these. If you get too comfortable with this "sloppy" (no offense) coding, it's very easy to start using them in cases where this really becomes an issue.

All this said, if it works for you, of course feel free to do it any way you feel comfortabe. I just wan't you to be aware of posible issues.
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
raider2k
Op


Joined: 01 Jan 2008
Posts: 140

PostPosted: Mon Mar 22, 2010 1:21 pm    Post subject: Reply with quote

ok, im always interested in becoming better, its just not clear enough to me what exactly i wasnt doing so properly.

is it about those " \ "'s ? if you dont mind please post me an example based on my code, i think that would help me out Smile

btw: i also remember you telling me to use split $text before i lindex it in another post some time ago, still remember and also using it Wink
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Mon Mar 22, 2010 3:50 pm    Post subject: Reply with quote

The improper thing is that you are handling a string as if it was a list. You can craft strings that tcl manages to interpret as lists, though it still is a string. For trivial list elements, this is fairly easy, but simply adding a space into the element makes it non-trivial. If you're not careful, it'll catch you offguard, giving you a nice headache.. Or if you use this with a Windows-style filesystem (using \ instead of /}).

You can indeed use split to convert a string into a proper list, and using lindex on a string is technically the same improper issue. However, "split $text" would often be used when the content of $text comes from a remote user, where you have no control what-so-ever of it's original content (hence you cannot quarantee it to be a valid list structure).

Actually, that's quite a good example how "sloppy" coding might sneak up and stab you in the back.. You get comfortable using something like this:
Code:
set keywords "hello dolly"
foreach key $keywords {
  bind msg - $key msg:hello
}

This is not proper, but since we're dealing with trivial elements, we get away with it - in fact, if we didn't read the manpages for foreach, we could come to believe that this will add a binding for each word of $keywords. We might even use it when writing a script to add multiple users to the bots userlist:
Code:
proc addusers {handle idx text} {
  foreach user $text {
    if {[adduser $user [hostmask $user![getchanhost $user]]]} {
      setuser $user PASS $user
    }
  }
}

It works well in a few simple tests... then you want to add someone named {badboy{ ... Now it doesn't work anymore, and you don't understand why it fails all of a sudden...
The solution here, is to use split to convert the string into a proper list.


To put it very simple, the difference between your code and mine, is that I use the list command to let tcl build a list, while you craft something resembling a list well enough for tcl to understand it.
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
raider2k
Op


Joined: 01 Jan 2008
Posts: 140

PostPosted: Tue Mar 23, 2010 12:45 am    Post subject: Reply with quote

i think ... im confused right now Shocked
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Tue Mar 23, 2010 9:06 am    Post subject: Reply with quote

Ahh, sorry.
I guess the simplest way of putting it is this:
Whenever a command expects a parameter value to be a list, make sure you are providing a list - not a string.
The simplest way of creating a list, is either to use the list command - or to split a string into a list. If you try to handcraft lists, you're bound to run into trouble sooner or later.

Oh, and regarding the examples in the previous post:
The first example demonstrates an improper script where I 'get away' with it because my string resembles a list well enough for tcl to understand it.
The second extends the improper scripting by accepting 'untrusted data' as a list - and it appears to work in most cases. Except in some non-trivial cases, where the script all of a sudden seems to stop working.

Your script is similar to example 1 right now. The step to something like example 2 isn't that far away...
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
raider2k
Op


Joined: 01 Jan 2008
Posts: 140

PostPosted: Tue Mar 23, 2010 1:22 pm    Post subject: Reply with quote

mhm, i think now i know what you mean Smile
very interesting, i hope ill keep that in mind Very Happy
thx nml ^^
Back to top
View user's profile Send private message
user
 


Joined: 18 Mar 2003
Posts: 1452
Location: Norway

PostPosted: Wed Mar 24, 2010 4:12 am    Post subject: Reply with quote

nml375 wrote:
Code:
if {[catch {source $script} err]} {

You are invoking 'source' in the scope of the proc, which means the code inside the sourced files is also executed in this scope. ("global" variables become local to the proc etc.) Use 'uplevel' to have it invoked in the right scope:
Code:
if {[catch [list uplevel #0 [list source $script]] err]} {

_________________
Have you ever read "The Manual"?
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Wed Mar 24, 2010 11:08 am    Post subject: Reply with quote

Nice catch, user. I'll update my post in a minute or so..
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
raider2k
Op


Joined: 01 Jan 2008
Posts: 140

PostPosted: Wed Mar 24, 2010 12:53 pm    Post subject: Reply with quote

W O N D E R F U L L Very Happy

because right now i wanted to ask why its coming up with some errors here and there, i think missing uplevel was the answer to that not-yet-asked-question Smile

thx again for help, thx to both of you Smile

btw: since the loadsource proc does a list on script from foreach scripts, am i safe to use set scripts { .... } now? im still a bit confused regarding that as i want to put each script into its own line, starting from the very first line until the last one, "set scripts [list" into the line before the first and "]" into the line after the last one. doing this now results in an error telling me that bot doesnt understand command "scripts/reg.tcl"
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 -> Scripting Help All times are GMT - 4 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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