Index: generic/threadCmd.c ================================================================== --- generic/threadCmd.c +++ generic/threadCmd.c @@ -282,10 +282,13 @@ ThreadIdleProc _ANSI_ARGS_((ClientData clientData)); static void ThreadExitProc _ANSI_ARGS_((ClientData clientData)); +static void +ThreadFreeError _ANSI_ARGS_((ClientData clientData)); + static void ListRemove _ANSI_ARGS_((ThreadSpecificData *tsdPtr)); static void ListRemoveInner _ANSI_ARGS_((ThreadSpecificData *tsdPtr)); @@ -619,13 +622,15 @@ return TCL_ERROR; } if (objc > 1) { if (OPT_CMP(Tcl_GetString(objv[1]), "-wait")) { wait = 1; - if (ThreadGetId(interp, objv[2], &thrId) != TCL_OK) { - return TCL_ERROR; - } + if (objc > 2) { + if (ThreadGetId(interp, objv[2], &thrId) != TCL_OK) { + return TCL_ERROR; + } + } } else if (ThreadGetId(interp, objv[1], &thrId) != TCL_OK) { return TCL_ERROR; } } @@ -1083,26 +1088,44 @@ if (objc == 1) { if (errorProcString) { Tcl_SetResult(interp, errorProcString, TCL_VOLATILE); } } else { - errorThreadId = Tcl_GetCurrentThread(); if (errorProcString) { Tcl_Free(errorProcString); } proc = Tcl_GetStringFromObj(objv[1], &len); if (len == 0) { + errorThreadId = NULL; errorProcString = NULL; } else { + errorThreadId = Tcl_GetCurrentThread(); errorProcString = Tcl_Alloc(1+strlen(proc)); strcpy(errorProcString, proc); + Tcl_DeleteThreadExitHandler(ThreadFreeError, NULL); + Tcl_CreateThreadExitHandler(ThreadFreeError, NULL); } } Tcl_MutexUnlock(&threadMutex); return TCL_OK; } + +static void +ThreadFreeError(clientData) + ClientData clientData; +{ + Tcl_MutexLock(&threadMutex); + if (errorThreadId != Tcl_GetCurrentThread()) { + Tcl_MutexUnlock(&threadMutex); + return; + } + Tcl_Free(errorProcString); + errorThreadId = NULL; + errorProcString = NULL; + Tcl_MutexUnlock(&threadMutex); +} /* *---------------------------------------------------------------------- * * ThreadJoinObjCmd -- @@ -2445,11 +2468,13 @@ */ if (thrId == Tcl_GetCurrentThread()) { Tcl_MutexUnlock(&threadMutex); if ((flags & THREAD_SEND_WAIT)) { - return (*send->execProc)(interp, (ClientData)send); + int code = (*send->execProc)(interp, (ClientData)send); + ThreadFreeProc((ClientData)send); + return code; } else { send->interp = interp; Tcl_Preserve((ClientData)send->interp); Tcl_DoWhenIdle((Tcl_IdleProc*)ThreadIdleProc, (ClientData)send); return TCL_OK; @@ -3129,10 +3154,11 @@ ret = (*sendPtr->execProc)(sendPtr->interp, (ClientData)sendPtr); if (ret != TCL_OK) { ThreadErrorProc(sendPtr->interp); } + ThreadFreeProc(clientData); Tcl_Release((ClientData)sendPtr->interp); } /* *---------------------------------------------------------------------- Index: generic/threadSpCmd.c ================================================================== --- generic/threadSpCmd.c +++ generic/threadSpCmd.c @@ -1070,10 +1070,17 @@ * Initializes shared hash table for storing sync primitive * handles and pointers. * *---------------------------------------------------------------------- */ + +static void +SpFinalize( + ClientData clientData) +{ + Tcl_Free((char *)clientData); +} int Sp_Init (interp) Tcl_Interp *interp; /* Interp where to create cmds */ { @@ -1082,10 +1089,12 @@ if (!initOnce) { Tcl_MutexLock(&initMutex); if (!initOnce) { int ii, buflen = sizeof(SpBucket) * (NUMSPBUCKETS); char *buf = Tcl_Alloc(2 * buflen); + + Tcl_CreateExitHandler(SpFinalize, buf); muxBuckets = (SpBucket*)(buf); varBuckets = (SpBucket*)(buf + buflen); for (ii = 0; ii < 2 * (NUMSPBUCKETS); ii++) { bucketPtr = &muxBuckets[ii]; memset(bucketPtr, 0, sizeof(SpBucket)); Index: generic/threadSvCmd.c ================================================================== --- generic/threadSvCmd.c +++ generic/threadSvCmd.c @@ -122,10 +122,11 @@ static int DeleteArray(Array*); static void SvAllocateContainers(Bucket*); static void SvRegisterStdCommands(void); +#define SV_FINALIZE #ifdef SV_FINALIZE static void SvFinalizeContainers(Bucket*); static void SvFinalize(ClientData); #endif /* SV_FINALIZE */ @@ -2181,10 +2182,12 @@ if (buckets == NULL) { Tcl_MutexLock(&bucketsMutex); if (buckets == NULL) { buckets = (Bucket *)Tcl_Alloc(sizeof(Bucket) * NUMBUCKETS); + Tcl_CreateExitHandler(SvFinalize, NULL); + for (i = 0; i < NUMBUCKETS; ++i) { bucketPtr = &buckets[i]; memset(bucketPtr, 0, sizeof(Bucket)); Tcl_InitHashTable(&bucketPtr->arrays, TCL_STRING_KEYS); Tcl_InitHashTable(&bucketPtr->handles, TCL_ONE_WORD_KEYS);