Posted to tcl by mr_calvin at Thu Dec 01 14:34:40 GMT 2016view pretty
proc ::cb {cmd args} { # onEnter: # cmdPtr->cmdEpoch = 1 (because Tcl_DeleteTokenFromCommand bumped it *before* executing traces (deleteProc) # resPtr->cmdEpoch = 0 # namespace origin will call Tcl_GetCommandFromObj (so checking Tcl_Obj cmd's cmdtype intrep) namespace origin $cmd # cmdPtr->cmdEpoch == resPtr->cmdEpoch evaluates to false, intrep is updated using the old cmd under deletion (!), then: # cmdPtr->cmdEpoch = 1 # resPtr->cmdEpoch = 1 (because cmd under deletion is used) # Sooo: from that time on, unless there is a second cmdEpoch++ # (2!=1) once traces (deleteProc) have been run, the Tcl_Obj # behind cmd will keep returning the wrongly? re-cached old cmd. } set cmd ::e set script { proc $cmd args {;} $cmd trace add command $cmd delete [list ::cb $cmd] rename $cmd ""; # trigger Tcl_DeleteTokenFromCommand + traces; rename (if I get it correctly) will also cmdEpoch++ a second time; so Tcl is fine, but we were not } # eval script block so that cmd becomes cmdType early. eval $script ## ## What we see (for our deleteProc, not traces) when creating a ## same-named cmd (::e) using $cmd, the Tcl_Objs cached cmdPtr points ## to the old cmd (which is a zombie once Tcl_DeleteCommandFromToken ## has completed.) So far, our deleteProc for the old cmd (::e) has ## not cmdEpoch++ on its own. We do so now and the problem goes away. ##
Comments
Posted by mr_calvin at Fri Dec 02 11:20:03 GMT 2016 [text] [code]
Hi Don, I tested http://core.tcl.tk/tcl/info/d3f2f88f49d64089. This solves the issue from our side (and cleans up cmdEpochs' state during deleteProc/delete traces). One thing: the repeated cmdEpoch++ before the final return is not necessary. one cmdEpoch++ is sufficient (i tested it from our side). just a left-over? (the second cmdEpoch++ I hinted above is only necessary because the first cmdEpoch++ occurred too early, before the deleteProc/ delete traces). thx.