Tcl Source Code

View Ticket
Login
Ticket UUID: 1338280
Title: unset traces during namespace delete misbehave
Type: Bug Version: obsolete: 8.4.11
Submitter: msofer Created on: 2005-10-26 09:53:00
Subsystem: 07. Variables Assigned To: msofer
Priority: 9 Immediate Severity:
Status: Closed Last Modified: 2005-11-04 09:14:57
Resolution: Fixed Closed By: msofer
    Closed on: 2005-11-04 02:14:57
Description:
(neuronstorm reports in clt:
http://groups.google.com/group/comp.lang.tcl/browse_frm/thread/91073af364234a81/3a1aa30e489f3eb0#3a1aa30e489f3eb0

The following script demonstrates an invalid result
(empty string element in list) from [info vars
?pattern?] during unset traces called during [namespace
delete].

----

 namespace eval ::ref {}

 set ::ref::var1 AAA
 trace add variable ::ref::var1 {unset} [list doTrace]

 set ::ref::var2 BBB
 trace add variable ::ref::var2 {unset} [list doTrace]

 proc doTrace {vtraced vidx op} {
        puts stdout "'[info vars ::ref::*]'"
 }

 namespace delete ::ref

 puts stdout "'[info vars ::ref::*]'"

----

Output on windows Tcl 8.5a4 is:
 '::ref::var1 ::ref::var2'
 '{} ::ref::var2'
 ''

Output on windows Tcl 8.4.5 is:
 '::ref::var1 ::ref::var2'
 '::ref::var2'
 ''

Tcl8.4.7 behaves like 8.4.5, core-8-4-branch like 8.5a4
User Comments: msofer added on 2005-11-04 09:14:57:
Logged In: YES 
user_id=148712

Attached 8.4 patch adapted and committed to both branches.

dgp added on 2005-11-03 00:10:20:

File Deleted - 154768:

dgp added on 2005-11-03 00:10:19:

File Added - 154778: 1338280-84.patch

dgp added on 2005-11-03 00:10:17:
Logged In: YES 
user_id=80530


that patch contained a memory
leak.  here's the corrected 
replacement.

dgp added on 2005-11-02 22:38:46:

File Added - 154768: 1338280-84.patch

dgp added on 2005-11-02 22:38:42:
Logged In: YES 
user_id=80530


Here's a different patch
(against 8-4-branch) without
the incompatibility of the first.

Please look it over.

dgp added on 2005-11-01 11:26:53:
Logged In: YES 
user_id=80530

the patch does introduce a
script-visible change, yes.

it's also a simple change
that fixes this bug and
allegedly 1337229.

Neither the tcl nor the
tcllib test suite care about
the change.

If something does care, then
let's think harder about this, but
not until we find something that
does care.

Crafting a fix for these bugs other
than the one attached here will
be very, very tricky indeed.  Unless
we delay variable unset traces until
the point where the namespace
variables are no longer accessible,
then the access must go somewhere,
and we're left with the recursive task
of cleaning *that* up.

I fear we may already have that
problem with command delete traces.

msofer added on 2005-11-01 04:45:32:
Logged In: YES 
user_id=148712

Patch not committed: it contradicts the comment in
TclTeardownNamespace:
 /*
  * Start by destroying the namespace's variable table,
  * since variables might trigger traces.
  */

In particular, the patch changes the behaviour of the script:

  namespace eval a {
      proc p {} {puts hi}
      trace add variable x unset {a::p;#}
      set x 1
   }
   namespace delete a

which prints 'hi' before the patch, and does not after the
patch. Note that these comments in the source are the only
documentation about the ordering of operations during
namespace deletion.

dgp added on 2005-11-01 02:25:10:

File Added - 154563: 1338280.patch

Logged In: YES 
user_id=80530

attached patch corrects the reported
problem and passes the test suite.

msofer added on 2005-10-30 02:02:53:
Logged In: YES 
user_id=148712

The fundamental problem is that, when a variable is unset
due to its namespace being deleted,  the variable exists
while the unset trace is running:

namespace eval a {trace add variable x unset {puts [catch
{set ::a::x}];#}; set x 1}
1
% unset a::x
1
% namespace eval a {trace add variable x unset {puts [catch
{set ::a::x}];#}; set x 1}
1
% namespace delete a
0

This is a very old bug - just verified that Tcl8.3.4 has it
too. It is probably also the cause of Bug 1337229.

msofer added on 2005-10-30 01:58:07:
Logged In: YES 
user_id=148712

As the order in which the variables are deleted is not
specified, this script has been modified an added to the
testsuite as Test trace-18.4:
    namespace eval ::ref {}
    set ::ref::var1 AAA
    trace add variable ::ref::var1 unset doTrace
    set ::ref::var2 BBB
    trace add variable ::ref::var2 {unset} doTrace
    proc doTrace {vtraced vidx op} {
global info
append info [catch {set ::$vtraced}][llength [info vars
::ref::*]]
    }
    set info {}
    namespace delete ::ref
    rename doTrace {}
    set info

Note that the returned value is 0201 up to 8.4.7, and 0202
for HEAD and 8-4-branch. 

Note also that the *correct* return value is 1110 - as a
variable should not exist when it's unset trace is running.

msofer added on 2005-10-26 19:52:56:
Logged In: YES 
user_id=148712

On the basis of which versions are buggy, this is presumed
to be caused by the 2004-05-22 commit.

Attachments: