Sysop: | Amessyroom |
---|---|
Location: | Fayetteville, NC |
Users: | 28 |
Nodes: | 6 (0 / 6) |
Uptime: | 53:11:12 |
Calls: | 422 |
Files: | 1,025 |
Messages: | 90,610 |
I'm attempting to get my head around preventing resource leaks, using
try and return. In fact I thought I had understood the mechanisms well
enough to use them and had come up with a structure like this:
proc allocateResources {} {
set obj1 [Some_mechanism]
try {
set obj2 [Some_other_mechanism]
try {
do_various_other_stuff
} on error {message errorDict} {
$obj2 destroy
return \
-code error \
-errorcode [dict get $errorDict -errorcode] \
-errorinfo [dict get $errorDict -errorinfo] \
$message
}
} on error {
$obj1 destroy
return \
-code error \
-errorcode [dict get $errorDict -errorcode] \
-errorinfo [dict get $errorDict -errorinfo] \
$message
}
return [list $obj1 $obj2]
}
If all is well, I expect the caller of allocateResources to destroy the objects when it has finished with them.
There are a couple of areas of this code that I don't completely (?!) understand:
1) I was assuming that if there was an error in do_various_other_stuff
if would be caught by the inner 'on error' clause, which would delete
obj2 and raise another error that would be caught by the outer 'on
error' clause, which would delete obj1. Experiment suggests that this
doesn't happen and the outer 'on error' clause isn't executed.
2) Originally, I wasn't including -errorinfo in the return statements in
the 'on error' clauses, but I found that the stack trace didn't properly identify the line causing the error. Including -errorinfo seems to have
cured that problem.
So,
Q1) Have I misunderstood the way try... works, or is my problem
elsewhere? I realise that I could do away with the nested try...
statement and check whether obj1 and obj2 exist and only destroy them if
they do, but that seems clunky.
Q2) Have I coded the return statements properly to get the error
information to propagate correctly? I have a vague memory of doing it
this way sometime in the past only for some other issue to emerge that I corrected by not using -errorinfo.
Thanks,
Alan
PS For what it's worth, I am using a home-built tcl9.0.0 on Linux Mint.
1) I was assuming that if there was an error in do_various_other_stuff
if would be caught by the inner 'on error' clause, which would delete
obj2 and raise another error that would be caught by the outer 'on
error' clause, which would delete obj1. Experiment suggests that this
doesn't happen and the outer 'on error' clause isn't executed.
2) Originally, I wasn't including -errorinfo in the return statements in
the 'on error' clauses, but I found that the stack trace didn't properly identify the line causing the error. Including -errorinfo seems to have
cured that problem.
Q1) Have I misunderstood the way try... works, or is my problem
elsewhere? I realise that I could do away with the nested try...
statement and check whether obj1 and obj2 exist and only destroy them if
they do, but that seems clunky.
Q2) Have I coded the return statements properly to get the error
information to propagate correctly? I have a vague memory of doing it
this way sometime in the past only for some other issue to emerge that I corrected by not using -errorinfo.
I'm attempting to get my head around preventing resource leaks, using
try and return.
On 06/12/2024 20:12, Alan Grunwald wrote:
On 06/12/2024 17:59, Ralf Fassel wrote:<all helpful context removed>
* Alan Grunwald <nospam.nurdglaw@gmail.com>
Thanks Ralf,
As I pointed out to Harald, deleting the objects in a finally clause
is explicitly not what I want to do since I wish to return them if
there are no errors. I believe that I need to propagate the error
explicitly if I add an on error clause. I'll see what happens if I do
return -options $errorDict $message rather than extracting and
specifying -code, -errorcode and -errorinfo. I guess if would help if
I could recall what issue emerged when I tried doing it that way in
the past, but sadly...
Thank you very much indeed. Modifying my genuine code to use
return -options $errorDict $message
makes everything work as I originally expected - the resources are
tidied away correctly, and the error is propagated properly.
I'm now a happy bunny, but am slightly troubled by wondering why my
original attempt didn't work. I've had a closer look at the try manpage
and see the statement
"If an exception (i.e. any non-ok result) occurs during the evaluation
of either the handler or the finally clause, the original exception's
status dictionary will be added to the new exception's status dictionary under the -during key."
which I had previously overlooked. I guess that no -during key is
included if I raise the error using -options, but I'm not convinced that there's anything on the try manpage that should make me expect that no
on error handler will be executed if there's a -during key. Granted this
is kind of weird stuff that I wouldn't expect to get right first (or
second or third) time, but I would hope to understand what's going on by
the time I have got it right!
Anyway, thanks again, further explanations would be welcome, but are by
no means essential :-)
Alan
On 07/12/2024 13:36, Harald Oehlmann wrote:
Am 06.12.2024 um 21:35 schrieb Alan Grunwald:
On 06/12/2024 20:12, Alan Grunwald wrote:
On 06/12/2024 17:59, Ralf Fassel wrote:
* Alan Grunwald <nospam.nurdglaw@gmail.com>
<even more helpful context removed>
Yes, the magic here is, that the error dict contains "-level 0".
This does not exit the proc and thus, the outer try is also executed.
Take care,
Thanks Harald,
I have a vague memory that I was including a -level flag on the return statement in the past when "issues emerged". I shall keep my fingers
crossed that I remember this discussion when strange things happen with
this technique in the future.
Alan