Menu

#4101 Too much errorinfo at catch

obsolete: 8.6a1
closed-fixed
5
2008-08-05
2008-08-04
No

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).

Discussion

  • Don Porter

    Don Porter - 2008-08-05

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

     
  • Don Porter

    Don Porter - 2008-08-05

    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.

     
  • Don Porter

    Don Porter - 2008-08-05

    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.

     
  • Don Porter

    Don Porter - 2008-08-05

    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.

     
  • Don Porter

    Don Porter - 2008-08-05

    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.

     
  • Don Porter

    Don Porter - 2008-08-05
     
  • Don Porter

    Don Porter - 2008-08-05

    Logged In: YES
    user_id=80530
    Originator: NO

    File Added: 2038069.patch

     
  • Don Porter

    Don Porter - 2008-08-05

    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.

     
  • miguel sofer

    miguel sofer - 2008-08-05
    • status: open --> closed-fixed
     
  • miguel sofer

    miguel sofer - 2008-08-05

    Logged In: YES
    user_id=148712
    Originator: NO

    committed, thx

     
  • Lars Hellström

    Lars Hellström - 2008-08-06

    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.

     
  • Nobody/Anonymous

    Logged In: NO

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

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