Forum Discussion
Bret_McGinnis_1
Nimbostratus
Sep 20, 2005TCL runtime errors
Hi, is there a way to capture and process iRule TCL runtime errors. On a few occasions I have created and tested an iRule and in our lab and it works fine. When I implement the iRule on a production BigIP it fails because I am trying to use a variable that does not exist. Or worse, it works on the active BigIP and fails on the standby when it becomes the active BigIP.
When an iRule fails because of a TCL erro the packet is dropped. It that the normal? can it be changed?
Global variables make this more difficult.
Regards,
12 Replies
- unRuleY_95363Historic F5 AccountFirst, yes it's normal that a TCL error causes the connection to be reset. Unfortunately, there really isn't another way to continue with the connection once the rule event returns an error.
There are two helpful tools in writing an iRule to be resilient to certain failures. The first is the use of the command "info exists" which is used to check whether a variable exists. If you are having problems with a variable that sometimes doesn't exist, then adding some logic that properly handles that case with the above command would be the right thing to do. The other helpful tool is the "catch" command. This command evaluates the argument and returns 0 or 1 depending on whether the evaluation returned an error or not. So, for example, you could write a rule that would in fact never fail like this:when HTTP_REQUEST { if { [catch { if { ... } { foo } else { bar } } myresult] != 0 } { log local0. "My rule failed: $myresult" } } - Bret_McGinnis_1
Nimbostratus
Hi,
Thanks. I have been using "if exist" but I missed one and typo'ed another.
Another problem has been the result of a calculation with mod 12. I checked for the source "if exist" and it passed. I performed the calculation and it failed because the source sometimes has nulls in it. I check for integer but if the number is to large the integer test fails.
The "catch" command look interesting. Are there any restriction as to what can be put inside the catch command. What happens to intermediate results when the catch fails. If the irule is changes the pool and the iRule fails after the pool command is executed. Does the new pool assigned valid.
Regards, - unRuleY_95363Historic F5 AccountThere is also "string is integer" which will return a boolean if the string contains a valid integer. You can also add -strict to make the empty string also return false. This does check for underflow and overflow integers.
As for the "catch" command you are quickly realizing why we simply abort the connection. As for the details, when a command completes successfully, it is in effect. So, if the pool command succeeded, then yes, it is in effect. However, if the rule failed before the pool command, then it would not be in effect. - Bret_McGinnis_1
Nimbostratus
This is good stuff. For the mod 12 calculation I will try the -strict option.
I understand the "catch" command issues. The two iRules I am most interested in catching errors should work well with the "catch" command.
The first doesn't change any it just monitors the pools and sends notification when thresholds are reached.
The second has overrides the default pool if a particular condition is met. If it fails before the pool is changed (which is the most likely based on where I am currently get the error then sending the request to the default pool is fine. There is nothing in the iRule after the pool is changed so I don't think I have to worry about it.
What do you think?
Regards, - Bret_McGinnis_1
Nimbostratus
Oh, I forgot to ask. If I "catch" the error do I lose the syslog message with the TCL error indicating what the problem was?
Regards, - unRuleY_95363Historic F5 AccountThat seems reasonable, however, you should be able to put more explicit checks around the area that the error is occuring. Maybe you can elaborate more on the error and we can help get to the bottom of that.
And, yes, using the catch will eat any syslog error which is why I added a log message to my example above. This will log basically the same error text that gets spit out when a rule fails. - Bret_McGinnis_1
Nimbostratus
Sorry to go radio silent for so long but writting iRules is not my day job.
Anyway, where were we ... Oh yes, I was working on two problems.
The mod 12 calculation works fine up until the number is larger than 9 digits. After 9 it fails the integer check. -strict has no effect.
For using catch to catch runtime errors works well until I added a "return" command within the catch. The return works but the check for != 0 always fails and I get a syslog message with no text. I tried using "return 0" (syslog message is "0". "return -code 0" also gets a syslog message with no text.
What am I doing wrong?
Another question I have is in regards to the [LB::server addr] variable. If is have a value ie an IP address should it pass an If info exist test. Second, if the LB_FAILED is caused by a real pool failure does [LB::server addr] have a null value or does it not exist?
Regards,
Bret - unRuleY_95363Historic F5 AccountThe mod 12 calculation works fine up until the number is larger than 9 digits. After 9 it fails the integer check. -strict has no effect.Hmm, I'm not sure what's going on here other than Tcl may not be properly handling mod on what it calls "wide integers" (64-bit integers). I'll try to look into it. In the meantime, you could try using the binary command to break the "wide integer" into two regular 32-bit integers and then do the appropriate math on the combination of those.
As for the catch with a return in it: catch returns several values. From the Tcl documentation on sourceforge: Tcl also defines four exceptional return codes: 1 (TCL_ERROR), 2 (TCL_RETURN), 3 (TCL_BREAK), and 4 (TCL_CONTINUE).So, if you are using a return, the catch is likely returning a value of 2 instead of 0. You should be able to modify the if check around the catch to more specifically look for a value of 1 to mean an error occurred instead of != 0.
Last, the [LB::server addr] is actually a command not a variable. Therefore you can't use "info exists" on it. It will return an empty string if a server was not picked (eg: the pool had no nodes available). - Bret_McGinnis_1
Nimbostratus
I'm back. The only outstanding issue on this thread is the TCL error when I terminate iRule processing using "return" while within a "catch". At the end of the catch I check the RC and if it is != 0 I send a log message with the error.
Normal processing: When the iRule completes (RC 0)and there were no errors I don't get a log message.
Exception processing: When the iRule encounter an error (TCL runtime - RC != 0) the iRules terminates and send a log message with the error from the catch command.
Return processing: I terminate the iRule by issuing a "return" command. I am expecting a RC 0 and not log message. What I am getting is RC 0 and a log message showing the error as "0".
What am I doing wrong?
Sample iRule:
if { [catch {
.... return
} lb_selected] != 0} {
log local0.error "iRule captured TCL error: $lb_selected"
}
Log message:
Nov 15 15:47:38 tmm tmm[705]: Rule xxxx : iRule captured TCL error: 0
Regards,
Bret - unRuleY_95363Historic F5 AccountChange it to only log the error if catch returns 1.
EG:
If you re-read the above parts of this post, you'll see that catch actually returns 2 if a return statement is encountered.if { [catch { ... } lb_selected] == 1 } { log local0.error "iRule captured TCL error: $lb_selected" }
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects
