Date: Tuesday, September 10, 2013 @ 05:10:02 Author: eric Revision: 194018
upgpkg: tk 8.6.0-3 Add patch to fix seg fault in xcircuit (close FS#36843) Added: tk/trunk/tk-xcircuit.patch Modified: tk/trunk/PKGBUILD -------------------+ PKGBUILD | 13 +- tk-xcircuit.patch | 317 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 326 insertions(+), 4 deletions(-) Modified: PKGBUILD =================================================================== --- PKGBUILD 2013-09-10 00:31:09 UTC (rev 194017) +++ PKGBUILD 2013-09-10 03:10:02 UTC (rev 194018) @@ -3,15 +3,21 @@ pkgname=tk pkgver=8.6.0 -pkgrel=2 +pkgrel=3 pkgdesc="A windowing toolkit for use with tcl" arch=('i686' 'x86_64') url="http://tcl.sourceforge.net/" license=('custom') depends=("tcl=${pkgver}" 'libxss' 'libxft') -source=(http://downloads.sourceforge.net/sourceforge/tcl/tk${pkgver}-src.tar.gz) -sha1sums=('c42e160285e2d26eae8c2a1e6c6f86db4fa7663b') +source=(http://downloads.sourceforge.net/sourceforge/tcl/tk${pkgver}-src.tar.gz tk-xcircuit.patch) +sha1sums=('c42e160285e2d26eae8c2a1e6c6f86db4fa7663b' + 'e0e75044d4e33533b0114d3c142b40b7280c364f') +prepare() { + cd tk${pkgver} + patch -p0 -i "${srcdir}/tk-xcircuit.patch" +} + build() { cd tk${pkgver}/unix [[ $CARCH == "x86_64" ]] && BIT="--enable-64bit" @@ -33,5 +39,4 @@ # remove buildroot traces sed -i "s#${srcdir}#/usr/src#" "${pkgdir}/usr/lib/tkConfig.sh" - } Added: tk-xcircuit.patch =================================================================== --- tk-xcircuit.patch (rev 0) +++ tk-xcircuit.patch 2013-09-10 03:10:02 UTC (rev 194018) @@ -0,0 +1,317 @@ +Index: generic/tkConfig.c +================================================================== +--- generic/tkConfig.c ++++ generic/tkConfig.c +@@ -29,11 +29,16 @@ + /* + * The following definition is an AssocData key used to keep track of all of + * the option tables that have been created for an interpreter. + */ + +-#define OPTION_HASH_KEY "TkOptionTable" ++typedef struct ThreadSpecificData { ++ int initialized; /* 0 means table below needs initializing. */ ++ Tcl_HashTable hashTable; ++} ThreadSpecificData; ++static Tcl_ThreadDataKey dataKey; ++ + + /* + * The following two structures are used along with Tk_OptionSpec structures + * to manage configuration options. Tk_OptionSpec is static templates that are + * compiled into the code of a widget or other object manager. However, to +@@ -98,12 +103,10 @@ + * templates, this points to the table + * corresponding to the next template in the + * chain. */ + int numOptions; /* The number of items in the options array + * below. */ +- int refCount2; /* Reference counter for controlling the freeing +- * of the memory occupied by this OptionTable */ + Option options[1]; /* Information about the individual options in + * the table. This must be the last field in + * the structure: the actual size of the array + * will be numOptions, not 1. */ + } OptionTable; +@@ -113,12 +116,10 @@ + */ + + static int DoObjConfig(Tcl_Interp *interp, char *recordPtr, + Option *optionPtr, Tcl_Obj *valuePtr, + Tk_Window tkwin, Tk_SavedOption *savePtr); +-static void DestroyOptionHashTable(ClientData clientData, +- Tcl_Interp *interp); + static void FreeResources(Option *optionPtr, Tcl_Obj *objPtr, + char *internalPtr, Tk_Window tkwin); + static Tcl_Obj * GetConfigList(char *recordPtr, + Option *optionPtr, Tk_Window tkwin); + static Tcl_Obj * GetObjectForOption(char *recordPtr, +@@ -168,42 +169,38 @@ + * in which this table will be used. */ + const Tk_OptionSpec *templatePtr) + /* Static information about the configuration + * options. */ + { +- Tcl_HashTable *hashTablePtr; + Tcl_HashEntry *hashEntryPtr; + int newEntry; + OptionTable *tablePtr; + const Tk_OptionSpec *specPtr, *specPtr2; + Option *optionPtr; + int numOptions, i; ++ ThreadSpecificData *tsdPtr = ++ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* +- * We use an AssocData value in the interpreter to keep a hash table of +- * all the option tables we've created for this application. This is used +- * for two purposes. First, it allows us to share the tables (e.g. in +- * several chains) and second, we use the deletion callback for the +- * AssocData to delete all the option tables when the interpreter is +- * deleted. The code below finds the hash table or creates a new one if it ++ * We use an TSD in the thread to keep a hash table of ++ * all the option tables we've created for this application. This is ++ * used for allowing us to share the tables (e.g. in several chains). ++ * The code below finds the hash table or creates a new one if it + * doesn't already exist. + */ + +- hashTablePtr = Tcl_GetAssocData(interp, OPTION_HASH_KEY, NULL); +- if (hashTablePtr == NULL) { +- hashTablePtr = ckalloc(sizeof(Tcl_HashTable)); +- Tcl_InitHashTable(hashTablePtr, TCL_ONE_WORD_KEYS); +- Tcl_SetAssocData(interp, OPTION_HASH_KEY, DestroyOptionHashTable, +- hashTablePtr); ++ if (!tsdPtr->initialized) { ++ Tcl_InitHashTable(&tsdPtr->hashTable, TCL_ONE_WORD_KEYS); ++ tsdPtr->initialized = 1; + } + + /* + * See if a table has already been created for this template. If so, just + * reuse the existing table. + */ + +- hashEntryPtr = Tcl_CreateHashEntry(hashTablePtr, (char *) templatePtr, ++ hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->hashTable, (char *) templatePtr, + &newEntry); + if (!newEntry) { + tablePtr = Tcl_GetHashValue(hashEntryPtr); + tablePtr->refCount++; + return (Tk_OptionTable) tablePtr; +@@ -218,11 +215,10 @@ + for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) { + numOptions++; + } + tablePtr = ckalloc(sizeof(OptionTable) + (numOptions * sizeof(Option))); + tablePtr->refCount = 1; +- tablePtr->refCount2 = 1; + tablePtr->hashEntryPtr = hashEntryPtr; + tablePtr->nextPtr = NULL; + tablePtr->numOptions = numOptions; + + /* +@@ -332,13 +328,20 @@ + Tk_OptionTable optionTable) /* The option table to delete. */ + { + OptionTable *tablePtr = (OptionTable *) optionTable; + Option *optionPtr; + int count; ++ ThreadSpecificData *tsdPtr = ++ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + +- tablePtr->refCount--; +- if (tablePtr->refCount > 0) { ++ if (tablePtr->refCount > 1) { ++ tablePtr->refCount--; ++ return; ++ } ++ ++ if (!tsdPtr->initialized || !Tcl_FindHashEntry(&tsdPtr->hashTable, ++ tablePtr->hashEntryPtr)) { + return; + } + + if (tablePtr->nextPtr != NULL) { + Tk_DeleteOptionTable((Tk_OptionTable) tablePtr->nextPtr); +@@ -354,66 +357,11 @@ + && (optionPtr->extra.monoColorPtr != NULL)) { + Tcl_DecrRefCount(optionPtr->extra.monoColorPtr); + } + } + Tcl_DeleteHashEntry(tablePtr->hashEntryPtr); +- tablePtr->refCount2--; +- if (tablePtr->refCount2 <= 0) { +- ckfree(tablePtr); +- } +-} +- +-/* +- *---------------------------------------------------------------------- +- * +- * DestroyOptionHashTable -- +- * +- * This function is the deletion callback associated with the AssocData +- * entry created by Tk_CreateOptionTable. It is invoked when an +- * interpreter is deleted, and deletes all of the option tables +- * associated with that interpreter. +- * +- * Results: +- * None. +- * +- * Side effects: +- * The option hash table is destroyed along with all of the OptionTable +- * structures that it refers to. +- * +- *---------------------------------------------------------------------- +- */ +- +-static void +-DestroyOptionHashTable( +- ClientData clientData, /* The hash table we are destroying */ +- Tcl_Interp *interp) /* The interpreter we are destroying */ +-{ +- Tcl_HashTable *hashTablePtr = clientData; +- Tcl_HashSearch search; +- Tcl_HashEntry *hashEntryPtr; +- +- for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search); +- hashEntryPtr != NULL; +- hashEntryPtr = Tcl_NextHashEntry(&search)) { +- OptionTable *tablePtr = Tcl_GetHashValue(hashEntryPtr); +- +- /* +- * The following statements do two tricky things: +- * 1. They ensure that the option table is deleted, even if there are +- * outstanding references to it. +- * 2. They ensure that Tk_DeleteOptionTable doesn't delete other +- * tables chained from this one; we'll do it when we come across +- * the hash table entry for the chained table (in fact, the chained +- * table may already have been deleted). +- */ +- +- tablePtr->refCount = 1; +- tablePtr->nextPtr = NULL; +- Tk_DeleteOptionTable((Tk_OptionTable) tablePtr); +- } +- Tcl_DeleteHashTable(hashTablePtr); +- ckfree(hashTablePtr); ++ ckfree(tablePtr); + } + + /* + *-------------------------------------------------------------- + * +@@ -1149,11 +1097,11 @@ + objPtr->typePtr->freeIntRepProc(objPtr); + } + objPtr->internalRep.twoPtrValue.ptr1 = (void *) tablePtr; + objPtr->internalRep.twoPtrValue.ptr2 = (void *) bestPtr; + objPtr->typePtr = &optionObjType; +- tablePtr->refCount2++; ++ tablePtr->refCount++; + return bestPtr; + + error: + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( +@@ -1222,16 +1170,13 @@ + + static void + FreeOptionInternalRep( + register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ + { +- register OptionTable *tablePtr = (OptionTable *) objPtr->internalRep.twoPtrValue.ptr1; ++ register Tk_OptionTable tablePtr = (Tk_OptionTable) objPtr->internalRep.twoPtrValue.ptr1; + +- tablePtr->refCount2--; +- if (tablePtr->refCount2 <= 0) { +- ckfree(tablePtr); +- } ++ Tk_DeleteOptionTable(tablePtr); + objPtr->typePtr = NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; + objPtr->internalRep.twoPtrValue.ptr2 = NULL; + } + +@@ -2111,27 +2056,27 @@ + Tk_OptionTable table) /* Table about which information is to be + * returned. May not necessarily exist in the + * interpreter anymore. */ + { + OptionTable *tablePtr = (OptionTable *) table; +- Tcl_HashTable *hashTablePtr; + Tcl_HashEntry *hashEntryPtr; + Tcl_HashSearch search; + Tcl_Obj *objPtr; ++ ThreadSpecificData *tsdPtr = ++ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + objPtr = Tcl_NewObj(); +- hashTablePtr = Tcl_GetAssocData(interp, OPTION_HASH_KEY, NULL); +- if (hashTablePtr == NULL) { ++ if (!tablePtr || !tsdPtr->initialized) { + return objPtr; + } + + /* + * Scan all the tables for this interpreter to make sure that the one we + * want still is valid. + */ + +- for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search); ++ for (hashEntryPtr = Tcl_FirstHashEntry(&tsdPtr->hashTable, &search); + hashEntryPtr != NULL; + hashEntryPtr = Tcl_NextHashEntry(&search)) { + if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) { + for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) { + Tcl_ListObjAppendElement(NULL, objPtr, + +Index: generic/tkTest.c +================================================================== +--- generic/tkTest.c ++++ generic/tkTest.c +@@ -801,10 +801,11 @@ + sizeof(char *), "table", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (tables[index] != NULL) { + Tk_DeleteOptionTable(tables[index]); ++ tables[index] = NULL; + } + break; + + case INFO: + if (objc != 3) { + +Index: tests/config.test +================================================================== +--- tests/config.test ++++ tests/config.test +@@ -96,11 +96,11 @@ + testobjconfig chain2 .b + testobjconfig chain1 .a + testobjconfig info chain2 + } -cleanup { + killTables +-} -result {1 4 -three 2 2 -one} ++} -result {2 4 -three 2 2 -one} + test config-1.8 {Tk_CreateOptionTable - chained tables} -constraints { + testobjconfig + } -body { + testobjconfig chain1 .a + testobjconfig chain2 .b +@@ -132,11 +132,11 @@ + lappend x [testobjconfig info chain2] [testobjconfig info chain1] + testobjconfig delete chain2 + lappend x [testobjconfig info chain2] [testobjconfig info chain1] + } -cleanup { + killTables +-} -result {{1 4 -three 2 2 -one} {2 2 -one} {} {1 2 -one}} ++} -result {{} {2 2 -one} {} {2 2 -one}} + + # No tests for DestroyOptionHashTable; couldn't figure out how to test. + + test config-3.1 {Tk_InitOptions - priority of chained tables} -constraints { + testobjconfig +