Posted to tcl by mr_calvin at Thu Dec 01 14:34:40 GMT 2016view raw
- 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.