Tcl Source Code

View Ticket
Login
Ticket UUID: 2038069
Title: Too much errorinfo at catch
Type: Bug Version: obsolete: 8.6a1
Submitter: lars_h Created on: 2008-08-04 21:42:19
Subsystem: 47. Bytecode Compiler Assigned To: msofer
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2008-08-07 03:57:27
Resolution: Fixed Closed By: msofer
    Closed on: 2008-08-05 15:55:16
Description:
This is an issue where a bytecompiled [catch] behaves differently from an interpreted [catch]. It is present in 8.5, today's CVS HEAD (8.6a1 with NRE), and at least 8.4 too (haven't checked with any 8.3 or earlier).

The issue is probably clearest in 8.5 (this is .0):

% proc compiled {prefix script} {list [catch [lappend prefix $script] res info] $res $info}
% proc interpreted {prefix script} {list [eval {catch [lappend prefix $script] res info}] $res $info}

(Same code, except for the [eval] around the [catch] in the latter. Changing the command substitution to a variable substitution did not seem to make a difference.)

% compiled {uplevel #0} {error FOO}
1 FOO {-code 1 -level 0 -errorcode NONE -errorinfo {FOO
    while executing
"error FOO"
    ("uplevel" body line 1)
    invoked from within
"uplevel #0 {error FOO}"
    invoked from within
"catch [lappend prefix $script] res info"} -errorline 1}

% interpreted {uplevel #0} {error FOO}
1 FOO {-code 1 -level 0 -errorcode NONE -errorinfo {FOO
    while executing
"error FOO"
    ("uplevel" body line 1)
    invoked from within
"uplevel #0 {error FOO}"} -errorline 1}

Thus: the compiled [catch] includes itself in the -errorinfo, whereas the interpreted does not. IMHO the latter is more correct. (If there was also a reliable way of dropping the [uplevel] I'd be all ears, but I can live with that.)

In today's 8.6a1+NRE, the compiled result is slightly different, but the interpreted result stays the same:

% compiled {uplevel #0} {error FOO}
1 FOO {-code 1 -level 0 -errorcode NONE -errorinfo {FOO
    while executing
"error FOO"
    ("uplevel" body line 1)
    invoked from within
"catch [lappend prefix $script] res info"} -errorline 1}

% interpreted {uplevel #0} {error FOO}
1 FOO {-code 1 -level 0 -errorcode NONE -errorinfo {FOO
    while executing
"error FOO"
    ("uplevel" body line 1)
    invoked from within
"uplevel #0 {error FOO}"} -errorline 1}

I actually find this compiled behaviour a change to the worse, because it places greater emphasis on irrelevant details (how the command being caught is constructed and caught) while hiding some more relevant details (what the command being caught is).
User Comments: [email protected] added on 2008-08-07 03:57:27:
Logged In: NO 


rather than use [eval], I'd use:

set catch catch
list [$catch [lappend prefix $script] res info] $res $info

lars_h added on 2008-08-07 03:41:38:
Logged In: YES 
user_id=938835
Originator: YES

OK, so you've restored the pre-NRE behaviour. An improvement, although it still has compiled [catch]es putting information about commands not actually caught in the -errorinfo. I consider that a bug too, although obviously one of low prioriity.

For now, I'll work around it by adding an [eval] to force use of the interpreted [catch] instead:

proc hubs::eval::do-8.5 {prefix script} {
   list [eval {catch [lappend prefix $script] res info}] $res $info
}

Re "all ears": OK, that idea is to switch context for the [catch] and use fully-qualified names for the variables to avoid overwriting other variables; nothing that really required TIP#90. (Which is good, since I also have a [hubs::eval::do-8.4] for use in older interpreters.)

There is no reentrancy problem, since the variables are only set when returning. That's good.

The trick works for prefixes of "uplevel $level" and "namespace eval $ns", but not for "interp eval $path". That's *bad*, because the latter is one of my use-cases. Close but no cigar, I'm afraid.

msofer added on 2008-08-05 22:55:16:
Logged In: YES 
user_id=148712
Originator: NO

committed, thx

dgp added on 2008-08-05 22:41:53:
Logged In: YES 
user_id=80530
Originator: NO


Attached patch is a fix, and includes
a test.

If miguel, or anyone has a better fix
that still passes the test, that's fine
with me.

After a fix is committed, I recommend
we close this report.  The other issues
raised seem to me to be feature requests.

dgp added on 2008-08-05 22:40:35:

File Added - 287168: 2038069.patch

Logged In: YES 
user_id=80530
Originator: NO

File Added: 2038069.patch

dgp added on 2008-08-05 22:18:23:
Logged In: YES 
user_id=80530
Originator: NO


Confirmed.  If I disable the
pure list branch at line 2604
of tclExecute.c HEAD, then this
regression goes away.  Some details
about stack trace generatation
went off down that branch.

dgp added on 2008-08-05 22:14:46:
Logged In: YES 
user_id=80530
Originator: NO


Not confident yet, but appears to be
a consequence of the re-implementation
of the INST_EVAL_STK instruction.

dgp added on 2008-08-05 22:02:08:
Logged In: YES 
user_id=80530
Originator: NO


Focusing just on the regression, uplevel
is a red herring.  Prior to miguel's NRE
commits on July 13:

% proc demo {} {
    list [catch [list set] m o] $m $o
}
% demo
1 {wrong # args: should be "set varName ?newValue?"} {-code 1 -level 0 -errorcode NONE -errorinfo {wrong # args: should be "set varName ?newValue?"
    while executing
"set"
    invoked from within
"catch [list set] m o"} -errorline 2}

After the commits of July 13 & 14:

% demo
1 {wrong # args: should be "set varName ?newValue?"} {-code 1 -level 0 -errorcode NONE -errorinfo {wrong # args: should be "set varName ?newValue?"
    while executing
"catch [list set] m o"} -errorline 2}

It is important that the script argument to
[catch] is the result of a substitution to
see this change.

dgp added on 2008-08-05 21:47:39:
Logged In: YES 
user_id=80530
Originator: NO


The stack trace change in 8.6 came
in with miguels original NRE commits
on July 13-14.

dgp added on 2008-08-05 21:13:43:
Logged In: YES 
user_id=80530
Originator: NO


To answer the "all ears" request first...

TIP 90 includes the following example
of how to use Tcl 8.5 features to
robustly remove the effects of catch
and uplevel from the stack trace of
a "wrapper" command:

namespace eval control {
     proc eval script {
         variable result
         variable options
         set code [uplevel 1 \
                 [list ::catch $script [namespace which -variable result] \
                         [namespace which -variable options]]]
         if {$code == 1} {
             set line [dict get $options -errorline]
             dict append options -errorinfo \
                     "\n    (\"[lindex [info level 0] 0]\" body line $line)"
         }
         dict incr options -level
         return -options $options $result
     }
 }

Attachments: