Ticket UUID: | 2662380 | |||
Title: | Bug in append | |||
Type: | Bug | Version: | obsolete: 8.5.9 | |
Submitter: | a3a3el | Created on: | 2009-03-04 17:01:47 | |
Subsystem: | 46. Traces | Assigned To: | msofer | |
Priority: | 9 Immediate | Severity: | ||
Status: | Closed | Last Modified: | 2011-04-13 20:36:28 | |
Resolution: | Fixed | Closed By: | msofer | |
Closed on: | 2011-04-13 13:36:28 | |||
Description: |
The following can crash 8.4, 8.5 and 8.6: array set a [list] trace variable a w unset_key proc unset_key { var key op } { puts stderr "$var, $key, $op" global a if { [info exists a($key)] } { puts stderr "Unsetting a($key)." unset a($key) } else { puts stderr "Cannot unset a($key)." } } append a(test) one two Since 8.4, Tcl_AppendObjCmd has stopped calling Tcl_ObjSetVar2, and calls TclPtrSetVar instead. However, although TclPtrSetVar returns iPtr->emptyObj if the variable has been unset by a trace, Tcl_AppendObjCmd is still checking for NULL, and so attempts to append the next argument. I've attached patches for the 8.4 and 8.5 branches, and the trunk. Az. | |||
User Comments: |
msofer added on 2011-04-13 20:36:28:
allow_comments - 1 msofer added on 2011-04-13 20:36:26: fixed in all 3 branches msofer added on 2011-04-12 18:39:41: The "gross change in write traces" covers 2 cases: * trace undefined the var: in that case, TclPtrSetVar should just clear the var and return NULL * trace converted the var to an array: so what do we do now? What should append/set/etc return? In 8.4: % trace add variable x write foo % proc foo {name args} {upvar 1 $name x; unset x; set x(1) 1} % append x 2 % set x can't read "x": variable is array % parray x x(1) = 1 msofer added on 2011-04-12 09:30:37: Crashes HEAD but not core-8-5-branch as of today. Valgrind however still dislikes it in 8.5 dgp added on 2009-04-08 21:42:01: I modified the test script so that the "Unsetting" messages reports the value of the variable about to be unset. Then testing on Tcl releases 7.6p2 and 8.3.5, I see they agree on this output: a, test, w Unsetting a(test) = one. a, test, w Unsetting a(test) = two. Without thinking too deeply about it, I admit, that output also makes sense to me. [append] can operate on a name of a non-existent variable, creating the variable by making the appending write to it. Write traces come after the writing, so at that point the variable exists, and the trace can unset it. We end up back where we started with no existing variable. Multiple arguments to append just means we repeat the cycle. Appears this report is exposing some flaws in some of the varName resolution caching machinery that's come in releases 8.4 and later. Fixing that right may take some time and thought (*), and since it appears the claims of "crashes" are incorrect, I'll leave this one to come back to. The submitted patches may well be the right answer, I'm not sure yet, but the flaws exposed are broader and deeper, so I'd prefer to be more certain about a more complete fix. (*) or at least some input from msofer. :) dgp added on 2009-04-08 20:32:48: Relevant tests: append-7.1 appendComp-7.1 namespace-8.6 trace-16.8,9,10,13,14 dgp added on 2009-04-08 02:25:39: I see no crash. On 8.4 I see: a, test, w Unsetting a(test). a, test, w Cannot unset a(test). On Tcl 8.5 and HEAD I see an uncaught errors, but not always the same one (!). Either : a, test, w Unsetting a(test). can't set "a(test)": upvar refers to element in deleted array while executing "append a(test) one two" (file "/home/dgp/2662380.tcl" line 20) or this: a, test, w Unsetting a(test). can't set "a(test)": upvar refers to variable in deleted namespace while executing "append a(test) one two" (file "/home/dgp/2662380.tcl" line 20) dkf added on 2009-04-05 00:34:36: data_type - 110894 a3a3el added on 2009-03-05 00:02:24: File Added - 316178: tclVar-trunk.diff File Added: tclVar-trunk.diff a3a3el added on 2009-03-05 00:02:08: File Added - 316176: tclVar-8.5.diff File Added: tclVar-8.5.diff a3a3el added on 2009-03-05 00:01:47: File Added - 316175: tclVar-8.4.diff |