Tcl Source Code

Check-in [c8510ad941]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:To use a Tcl_Command token [aka (Command *)] for epoch checking, we must not permit it to be freed while we hold it or else it could be mistaken for another token allocated later that just happens to reside at the same address.

(Command *) preservation machinery already exists, just need to use it.

An extension facing the same problem might have to rely on command delete traces.

Earlier revisions used (Namespace *) lifetime to achieve the same results, but that's really an indirect (possibly non-robust) path to achieving the proper goal.

Valgrind is happy now.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dgp-ecr
Files: files | file ages | folders
SHA1: c8510ad9416e44e83f277432d7c1d2d648257a8d
User & Date: dgp 2016-07-07 18:44:56
Context
2016-07-07
19:50
Missed a cleanup line, which created a memleak. Closed-Leaf check-in: 355146f0e0 user: dgp tags: dgp-ecr
18:44
To use a Tcl_Command token [aka (Command *)] for epoch checking, we must not permit it to be freed w... check-in: c8510ad941 user: dgp tags: dgp-ecr
2016-07-01
19:42
The EnsembleCmdRep struct that is the internal rep for caching ensemble dispatches and spelling corr... check-in: ac4dbb12dd user: dgp tags: dgp-ecr
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclEnsemble.c.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
....
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
....
2400
2401
2402
2403
2404
2405
2406

2407
2408
2409
2410
2411
2412
2413
2414
....
2786
2787
2788
2789
2790
2791
2792

2793
2794
2795
2796
2797
2798
2799
....
2823
2824
2825
2826
2827
2828
2829

2830
2831
2832
2833
2834
2835
2836
 * spell corrections.
 */

typedef struct {
    int epoch;                  /* Used to confirm when the data in this
                                 * really structure matches up with the
                                 * ensemble. */
    Tcl_Command token;          /* Reference to the comamnd for which this
                                 * structure is a cache of the resolution. */
    Tcl_Obj *fix;               /* Corrected spelling, if needed. */
    Tcl_HashEntry *hPtr;        /* Direct link to entry in the subcommand
                                 * hash table. */
} EnsembleCmdRep;

 
................................................................................
	 * part where we do the invocation of the subcommand.
	 */

	if (subObj->typePtr==&ensembleCmdType){
	    EnsembleCmdRep *ensembleCmd = subObj->internalRep.twoPtrValue.ptr1;

	    if (ensembleCmd->epoch == ensemblePtr->epoch &&
		    ensembleCmd->token == ensemblePtr->token) {
		prefixObj = Tcl_GetHashValue(ensembleCmd->hPtr);
		Tcl_IncrRefCount(prefixObj);
		if (ensembleCmd->fix) {
		    TclSpellFix(interp, objv, objc, subIdx, subObj, ensembleCmd->fix);
		}
		goto runResultingSubcommand;
	    }
................................................................................
    }

    /*
     * Populate the internal rep.
     */

    ensembleCmd->epoch = ensemblePtr->epoch;

    ensembleCmd->token = ensemblePtr->token;
    if (fix) {
	Tcl_IncrRefCount(fix);
    }
    ensembleCmd->fix = fix;
    ensembleCmd->hPtr = hPtr;
}
 
................................................................................

static void
FreeEnsembleCmdRep(
    Tcl_Obj *objPtr)
{
    EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;


    if (ensembleCmd->fix) {
	Tcl_DecrRefCount(ensembleCmd->fix);
    }
    ckfree(ensembleCmd);
    objPtr->typePtr = NULL;
}
 
................................................................................
    EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
    EnsembleCmdRep *ensembleCopy = ckalloc(sizeof(EnsembleCmdRep));

    copyPtr->typePtr = &ensembleCmdType;
    copyPtr->internalRep.twoPtrValue.ptr1 = ensembleCopy;
    ensembleCopy->epoch = ensembleCmd->epoch;
    ensembleCopy->token = ensembleCmd->token;

    ensembleCopy->fix = ensembleCmd->fix;
    if (ensembleCopy->fix) {
	Tcl_IncrRefCount(ensembleCopy->fix);
    }
    ensembleCopy->hPtr = ensembleCmd->hPtr;
}
 






|







 







|







 







>
|







 







>







 







>







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
....
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
....
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
....
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
....
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
 * spell corrections.
 */

typedef struct {
    int epoch;                  /* Used to confirm when the data in this
                                 * really structure matches up with the
                                 * ensemble. */
    Command *token;             /* Reference to the command for which this
                                 * structure is a cache of the resolution. */
    Tcl_Obj *fix;               /* Corrected spelling, if needed. */
    Tcl_HashEntry *hPtr;        /* Direct link to entry in the subcommand
                                 * hash table. */
} EnsembleCmdRep;

 
................................................................................
	 * part where we do the invocation of the subcommand.
	 */

	if (subObj->typePtr==&ensembleCmdType){
	    EnsembleCmdRep *ensembleCmd = subObj->internalRep.twoPtrValue.ptr1;

	    if (ensembleCmd->epoch == ensemblePtr->epoch &&
		    ensembleCmd->token == (Command *)ensemblePtr->token) {
		prefixObj = Tcl_GetHashValue(ensembleCmd->hPtr);
		Tcl_IncrRefCount(prefixObj);
		if (ensembleCmd->fix) {
		    TclSpellFix(interp, objv, objc, subIdx, subObj, ensembleCmd->fix);
		}
		goto runResultingSubcommand;
	    }
................................................................................
    }

    /*
     * Populate the internal rep.
     */

    ensembleCmd->epoch = ensemblePtr->epoch;
    ensembleCmd->token = (Command *) ensemblePtr->token;
    ensembleCmd->token->refCount++;
    if (fix) {
	Tcl_IncrRefCount(fix);
    }
    ensembleCmd->fix = fix;
    ensembleCmd->hPtr = hPtr;
}
 
................................................................................

static void
FreeEnsembleCmdRep(
    Tcl_Obj *objPtr)
{
    EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;

    TclCleanupCommandMacro(ensembleCmd->token);
    if (ensembleCmd->fix) {
	Tcl_DecrRefCount(ensembleCmd->fix);
    }
    ckfree(ensembleCmd);
    objPtr->typePtr = NULL;
}
 
................................................................................
    EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
    EnsembleCmdRep *ensembleCopy = ckalloc(sizeof(EnsembleCmdRep));

    copyPtr->typePtr = &ensembleCmdType;
    copyPtr->internalRep.twoPtrValue.ptr1 = ensembleCopy;
    ensembleCopy->epoch = ensembleCmd->epoch;
    ensembleCopy->token = ensembleCmd->token;
    ensembleCopy->token->refCount++;
    ensembleCopy->fix = ensembleCmd->fix;
    if (ensembleCopy->fix) {
	Tcl_IncrRefCount(ensembleCopy->fix);
    }
    ensembleCopy->hPtr = ensembleCmd->hPtr;
}