summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2012-06-25 14:43:36 (GMT)
committerdgp <dgp@users.sourceforge.net>2012-06-25 14:43:36 (GMT)
commitc56279aca031cd571054139f95be82bb90c7dbfa (patch)
treec871ead30ab5ffe77b435d00aead35267d1695d9
parent01eab1b3890706a987bfd038c2193a060660d823 (diff)
parent527a4f67fa396747502ba37514a882725f401110 (diff)
downloadtcl-bug_3024359.zip
tcl-bug_3024359.tar.gz
tcl-bug_3024359.tar.bz2
Simplify bug fix so that active claims on the FilesystemRecord list of a threadbug_3024359
prevent any overwriting of that per-thread cache. This keeps active traversals of the list valid. The possible downside is that this may result in some delay in noticing new epochs and result in somewhat greater likelihood we will cache things in a "path" value that are out of date. Since the system has to deal with out of date cached data anyway, this should have no correctness affects, measured against the status quo. In multi-threaded operation the possibility of caching and/or retrieving outdated information can never be eliminated. Checkin also includes merge of 8.5.
-rw-r--r--ChangeLog5
-rw-r--r--generic/tclCmdAH.c18
-rw-r--r--generic/tclIOUtil.c69
-rw-r--r--generic/tclPathObj.c3
-rw-r--r--tests/encoding.test8
5 files changed, 42 insertions, 61 deletions
diff --git a/ChangeLog b/ChangeLog
index c8ecc4f..e2ca3f2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-06-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclCmdAH.c (EncodingDirsObjCmd): [Bug 3537605]: Do the right
+ thing when reporting errors with the number of arguments.
+
2012-06-25 Jan Nijtmans <nijtmans@users.sf.net>
* generic/tclfileName.c: [Patch #1536227]: Cygwin network pathname
diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c
index e1ec927..8e32389 100644
--- a/generic/tclCmdAH.c
+++ b/generic/tclCmdAH.c
@@ -505,7 +505,7 @@ Tcl_EncodingObjCmd(
break;
}
case ENC_DIRS:
- return EncodingDirsObjCmd(dummy, interp, objc-1, objv+1);
+ return EncodingDirsObjCmd(dummy, interp, objc, objv);
case ENC_NAMES:
if (objc > 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
@@ -552,20 +552,24 @@ EncodingDirsObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- if (objc > 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "?dirList?");
+ Tcl_Obj *dirListObj;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?dirList?");
return TCL_ERROR;
}
- if (objc == 1) {
+ if (objc == 2) {
Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath());
return TCL_OK;
}
- if (Tcl_SetEncodingSearchPath(objv[1]) == TCL_ERROR) {
+
+ dirListObj = objv[2];
+ if (Tcl_SetEncodingSearchPath(dirListObj) == TCL_ERROR) {
Tcl_AppendResult(interp, "expected directory list but got \"",
- TclGetString(objv[1]), "\"", NULL);
+ TclGetString(dirListObj), "\"", NULL);
return TCL_ERROR;
}
- Tcl_SetObjResult(interp, objv[1]);
+ Tcl_SetObjResult(interp, dirListObj);
return TCL_OK;
}
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index 9d81d18..dccbeb5 100644
--- a/generic/tclIOUtil.c
+++ b/generic/tclIOUtil.c
@@ -586,31 +586,19 @@ static void
FsRecacheFilesystemList(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
- FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL, *toFree = NULL, *chain = NULL;
+ FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL, *toFree = NULL, *list;
/*
* Trash the current cache.
*/
fsRecPtr = tsdPtr->filesystemList;
- if (tsdPtr->claims <= 0) {
- while (fsRecPtr != NULL) {
- tmpFsRecPtr = fsRecPtr->nextPtr;
- fsRecPtr->fsPtr = NULL;
- fsRecPtr->nextPtr = toFree;
- toFree = fsRecPtr;
- fsRecPtr = tmpFsRecPtr;
- }
- } else {
- chain = fsRecPtr;
- while (fsRecPtr->nextPtr != NULL) {
- fsRecPtr->prevPtr = fsRecPtr->nextPtr;
- fsRecPtr->nextPtr = NULL;
- fsRecPtr = fsRecPtr->prevPtr;
- }
- fsRecPtr->prevPtr = fsRecPtr;
+ while (fsRecPtr != NULL) {
+ tmpFsRecPtr = fsRecPtr->nextPtr;
+ fsRecPtr->nextPtr = toFree;
+ toFree = fsRecPtr;
+ fsRecPtr = tmpFsRecPtr;
}
- tsdPtr->filesystemList = NULL;
/*
* Locate tail of the global filesystem list.
@@ -627,24 +615,26 @@ FsRecacheFilesystemList(void)
* Refill the cache honouring the order.
*/
+ list = NULL;
fsRecPtr = tmpFsRecPtr;
while (fsRecPtr != NULL) {
tmpFsRecPtr = (FilesystemRecord *) ckalloc(sizeof(FilesystemRecord));
*tmpFsRecPtr = *fsRecPtr;
- tmpFsRecPtr->nextPtr = tsdPtr->filesystemList;
- tmpFsRecPtr->prevPtr = chain;
- chain = NULL;
- tsdPtr->filesystemList = tmpFsRecPtr;
+ tmpFsRecPtr->nextPtr = list;
+ tmpFsRecPtr->prevPtr = NULL;
+ list = tmpFsRecPtr;
fsRecPtr = fsRecPtr->prevPtr;
}
+ tsdPtr->filesystemList = list;
+ tsdPtr->filesystemEpoch = theFilesystemEpoch;
+ Tcl_MutexUnlock(&filesystemMutex);
while (toFree) {
FilesystemRecord *next = toFree->nextPtr;
+ toFree->fsPtr = NULL;
ckfree((char *)toFree);
toFree = next;
}
- tsdPtr->filesystemEpoch = theFilesystemEpoch;
- Tcl_MutexUnlock(&filesystemMutex);
/*
* Make sure the above gets released on thread exit.
@@ -660,8 +650,8 @@ static FilesystemRecord *
FsGetFirstFilesystem(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
- if (tsdPtr->filesystemList == NULL
- || (tsdPtr->filesystemEpoch != theFilesystemEpoch)) {
+ if (tsdPtr->filesystemList == NULL || ((tsdPtr->claims == 0)
+ && (tsdPtr->filesystemEpoch != theFilesystemEpoch))) {
FsRecacheFilesystemList();
}
return tsdPtr->filesystemList;
@@ -683,7 +673,6 @@ static void
Claim()
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
-
tsdPtr->claims++;
}
@@ -691,31 +680,7 @@ static void
Disclaim()
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
- FilesystemRecord *fsRecPtr, *toRelease, *lastCurrent;
-
- if (--tsdPtr->claims > 0) {
- return;
- }
- fsRecPtr = tsdPtr->filesystemList;
-
- /*
- * Release all out of date FilesystemRecords.
- * First skip the current list.
- */
- while (fsRecPtr->nextPtr != NULL) {
- fsRecPtr = fsRecPtr->nextPtr;
- }
-
- /* Then release everything that comes after. */
- lastCurrent = fsRecPtr;
- toRelease = lastCurrent->prevPtr;
- lastCurrent->prevPtr = NULL;
- while (toRelease != NULL) {
- fsRecPtr = (toRelease == toRelease->prevPtr) ? NULL
- : toRelease->prevPtr;
- ckfree((char *)toRelease);
- toRelease = fsRecPtr;
- }
+ tsdPtr->claims--;
}
/*
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c
index 66cc617..4e1172a 100644
--- a/generic/tclPathObj.c
+++ b/generic/tclPathObj.c
@@ -563,8 +563,7 @@ TclPathPart(
if (pathPtr->typePtr == &tclFsPathType) {
FsPath *fsPathPtr = PATHOBJ(pathPtr);
- if (/*TclFSEpochOk(fsPathPtr->filesystemEpoch)
- && */(PATHFLAGS(pathPtr) != 0)) {
+ if (PATHFLAGS(pathPtr) != 0) {
switch (portion) {
case TCL_PATH_DIRNAME: {
/*
diff --git a/tests/encoding.test b/tests/encoding.test
index 836f277..aa50360 100644
--- a/tests/encoding.test
+++ b/tests/encoding.test
@@ -586,6 +586,14 @@ file delete {*}[glob -directory [temporaryDirectory] *.chars *.tcltestout]
# EscapeFreeProc, GetTableEncoding, unilen
# are fully tested by the rest of this file
+
+test encoding-27.1 {encoding dirs basic behavior} -returnCodes error -body {
+ encoding dirs ? ?
+} -result {wrong # args: should be "encoding dirs ?dirList?"}
+test encoding-27.2 {encoding dirs basic behavior} -returnCodes error -body {
+ encoding dirs "\{not a list"
+} -result "expected directory list but got \"\{not a list\""
+
}
runtests