TIP 211: Add Full Stack Trace Capability

Login
Author:         Robert Seeger <[email protected]>
Author:         Robert Seeger <[email protected]>
Author:         Don Porter <[email protected]>
State:          Withdrawn
Type:           Project
Vote:           Pending
Created:        10-Aug-2004
Post-History:   
Keywords:       Tcl
Tcl-Version:    8.5
Obsoleted-By:	280

Abstract

This TIP proposes adding a new subcommand to the info command to get a list of all the frames on the current stack, rather than the limited list returned by info level.

Rationale

Currently, there is no way to get a list of all the frames in the current stack managed by Tcl_PushCallFrame() and Tcl_PopCallFrame(). The info level command does not contain frames that are callers of uplevel, reporting only the frames that are accessible via another uplevel command. There are times when the lack of information can have a negative impact on code design. The difference in information can be seen with the following code snippets:

% proc bob {args} { 
    joe {expand}$args
  }
% proc joe {args} {
    uplevel 1 dave {expand}$args
  }
% proc dave {args} {
    puts "Level: [info level]"
    for {set i [info level]} { $i > 0 } {incr i -1 } {
      puts "${i}: [info level $i]"
    }
  }
% bob x y z
Level: 2
2: dave x y z
1: bob x y z
% proc dave {args} {
    puts "Level: [info frame]" 
    for {set i [info frame]} { $i > 0 } {incr i -1 } {
      puts "${i}: [info frame $i]"
    }
  }
% bob
Level: 3
3: dave x y z
2: joe x y z
1: bob x y z

There are 3 reasons I see for bringing forth this TIP:

  1. It's an introspection ability that is currently lacking, with no good reason for that lack.

  2. The more information that is available to the programmer, the easier it is to accomplish a goal in a straightforward, easily maintainable way.

  3. I have code in which the impact of not having this information available is visible.

Use Cases

There are two cases I have run into where the ability to query all frames on the stack would have been particularly useful.

  1. TclTest

    The first case is with Tcltest, where the complete lack of ability to gain access to that information means it is impossible to gain information about a test without modifying the Tcltest code itself. Being able to find out the name of the current test would be very handy, especially in naming test procs and logging information. Currently, there is no way to find out the name of the currently executing test, due to the fact that the code for the test is upleveled and, hence, not visible via info level.

  2. TestStubs Package

    The TestStubs package provides the ability to temporarily redefine commands, in particular for stubbing out or replacing functionality in a test case. There is a command in the package called chain, which is used within the code replacing a command (or part of a command) to call the original definition of the command. For example, one could do:

    stubs::stub ensemble array names {
        return [lsort [uplevel 1 chain names $args]]
    }
    

    However, since the chain command is (and should be) limited to only running from within a stub definition, it needs to call info level to find out if its caller is one of the stubbed commands, and what the name of that command is. With info level, it would not have access to the level that is running inside the stubbed procedure. Hence, either it cannot check this constraint, or stubs cannot be allowed to use uplevel when calling it (which means things like the above either cannot work, or need to be rewritten in a considerably less clear manner).

Proposed Change

I propose to add a new subcommand to the info command with the following syntax:

info frame ?level?

The new functionality will provide access to all frames on the stack rather than the current limited subset. The information to do so already exists within the Interp object that all commands are passed, and the code needed to expose it differs in only a few aspects from that of info level.

This TIP does not propose to alter uplevel or upvar so that they can see these hidden levels.

Child Interps

The current implementation of info level only returns levels up to the top of the stack for the current interpreter. Such an approach puts limitations on what information can be retrieved, but allows for a certain level of "security" when running code in child interps, especially safe interps.

Given the security considerations of safe interps, and consistancy with regards to what information is returned across multiple circumstances, the stack trace returned will only return information up to the top level of the current interp, the same limit info level is bound by.

Implementation

An implementation patch is available on SourceForge http://sourceforge.net/tracker/?func=detail&aid=1503647&group_id=10894&atid=310894 .

Copyright

This document has been placed in the public domain.

Please note that any correspondence to the author concerning this TIP is considered in the public domain unless otherwise specifically requested by the individual(s) authoring said correspondence. This is to allow information about the TIP to be placed in a public forum for discussion.