From 817534697915bca720f02388c1e9b6a0e72718c0 Mon Sep 17 00:00:00 2001 From: andreas_kupries Date: Wed, 7 Oct 2009 23:10:50 +0000 Subject: * generic/tclObj.c: [Bug 2871908]: Plug memory leaks of the objThreadMap and lineCLPtr hashtables. Also make the names of the continuation line information initialization and finalization functions more consistent. Patch supplied by Joe Mistachkin . --- ChangeLog | 6 +++++ generic/tclEvent.c | 3 ++- generic/tclObj.c | 73 ++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6d4f1b5..53932ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2009-10-07 Andreas Kupries + * generic/tclObj.c: [Bug 2871908]: Plug memory leaks of the + objThreadMap and lineCLPtr hashtables. Also make the names of the + continuation line information initialization and finalization + functions more consistent. Patch supplied by Joe Mistachkin + . + * generic/tclIORChan.c (ErrnoReturn): Replace the hardwired constant 11 with the proper errno define, EAGAIN. What was I thinking ? The BSD's have a different errno assignment and break diff --git a/generic/tclEvent.c b/generic/tclEvent.c index 299922f..a10da8f 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclEvent.c,v 1.80.2.1 2009/04/27 21:45:20 ferrieux Exp $ + * RCS: @(#) $Id: tclEvent.c,v 1.80.2.2 2009/10/07 23:10:50 andreas_kupries Exp $ */ #include "tclInt.h" @@ -1239,6 +1239,7 @@ Tcl_FinalizeThread(void) TclFinalizeIOSubsystem(); TclFinalizeNotifier(); TclFinalizeAsync(); + TclFinalizeThreadObjects(); } /* diff --git a/generic/tclObj.c b/generic/tclObj.c index 1b0a58c..39b8515 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclObj.c,v 1.139.2.3 2009/08/25 21:01:05 andreas_kupries Exp $ + * RCS: @(#) $Id: tclObj.c,v 1.139.2.4 2009/10/07 23:10:50 andreas_kupries Exp $ */ #include "tclInt.h" @@ -88,8 +88,8 @@ typedef struct ThreadSpecificData { static Tcl_ThreadDataKey dataKey; static void ContLineLocFree (char* clientData); -static void TclThreadFinalizeObjects (ClientData clientData); -static ThreadSpecificData* TclGetTables (void); +static void TclThreadFinalizeContLines (ClientData clientData); +static ThreadSpecificData* TclGetContLineTable (void); /* * Nested Tcl_Obj deletion management support @@ -410,6 +410,49 @@ TclInitObjSubsystem(void) /* *---------------------------------------------------------------------- * + * TclFinalizeThreadObjects -- + * + * This function is called by Tcl_FinalizeThread to clean up thread + * specific Tcl_Obj information. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeThreadObjects(void) +{ +#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS) + Tcl_HashEntry *hPtr; + Tcl_HashSearch hSearch; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + Tcl_HashTable *tablePtr = tsdPtr->objThreadMap; + + if (tablePtr != NULL) { + for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { + ObjData *objData = Tcl_GetHashValue(hPtr); + + if (objData != NULL) { + ckfree((char *) objData); + } + } + + Tcl_DeleteHashTable(tablePtr); + ckfree((char *) tablePtr); + tsdPtr->objThreadMap = NULL; + } +#endif +} + +/* + *---------------------------------------------------------------------- + * * TclFinalizeObjects -- * * This function is called by Tcl_Finalize to clean up all registered @@ -447,7 +490,7 @@ TclFinalizeObjects(void) /* *---------------------------------------------------------------------- * - * TclGetTables -- + * TclGetContLineTable -- * * This procedure is a helper which returns the thread-specific * hash-table used to track continuation line information associated with @@ -464,7 +507,7 @@ TclFinalizeObjects(void) */ static ThreadSpecificData* -TclGetTables() +TclGetContLineTable() { /* * Initialize the hashtable tracking invisible continuation lines. For @@ -478,10 +521,7 @@ TclGetTables() if (!tsdPtr->lineCLPtr) { tsdPtr->lineCLPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable)); Tcl_InitHashTable(tsdPtr->lineCLPtr, TCL_ONE_WORD_KEYS); - Tcl_CreateThreadExitHandler (TclThreadFinalizeObjects,NULL); -#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS) - tsdPtr->objThreadMap = NULL; -#endif /* TCL_MEM_DEBUG && TCL_THREADS */ + Tcl_CreateThreadExitHandler (TclThreadFinalizeContLines,NULL); } return tsdPtr; } @@ -510,7 +550,7 @@ TclContinuationsEnter(Tcl_Obj* objPtr, int* loc) { int newEntry; - ThreadSpecificData *tsdPtr = TclGetTables(); + ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry* hPtr = Tcl_CreateHashEntry (tsdPtr->lineCLPtr, (char*) objPtr, &newEntry); @@ -641,7 +681,7 @@ TclContinuationsEnterDerived(Tcl_Obj* objPtr, int start, int* clNext) void TclContinuationsCopy(Tcl_Obj* objPtr, Tcl_Obj* originObjPtr) { - ThreadSpecificData *tsdPtr = TclGetTables(); + ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char*) originObjPtr); if (hPtr) { @@ -673,7 +713,7 @@ TclContinuationsCopy(Tcl_Obj* objPtr, Tcl_Obj* originObjPtr) ContLineLoc* TclContinuationsGet(Tcl_Obj* objPtr) { - ThreadSpecificData *tsdPtr = TclGetTables(); + ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char*) objPtr); if (hPtr) { @@ -686,7 +726,7 @@ TclContinuationsGet(Tcl_Obj* objPtr) /* *---------------------------------------------------------------------- * - * TclThreadFinalizeObjects -- + * TclThreadFinalizeContLines -- * * This procedure is a helper which releases all continuation line * information currently known. It is run as a thread exit handler. @@ -702,15 +742,15 @@ TclContinuationsGet(Tcl_Obj* objPtr) */ static void -TclThreadFinalizeObjects (ClientData clientData) +TclThreadFinalizeContLines (ClientData clientData) { /* * Release the hashtable tracking invisible continuation lines. */ + ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry *hPtr; Tcl_HashSearch hSearch; - ThreadSpecificData *tsdPtr = TclGetTables(); for (hPtr = Tcl_FirstHashEntry(tsdPtr->lineCLPtr, &hSearch); hPtr != NULL; @@ -725,6 +765,7 @@ TclThreadFinalizeObjects (ClientData clientData) Tcl_DeleteHashEntry (hPtr); } Tcl_DeleteHashTable (tsdPtr->lineCLPtr); + ckfree((char *) tsdPtr->lineCLPtr); tsdPtr->lineCLPtr = NULL; } @@ -956,7 +997,7 @@ TclDbInitNewObj( Tcl_HashEntry *hPtr; Tcl_HashTable *tablePtr; int isNew; - ThreadSpecificData *tsdPtr = TclGetTables(); + ThreadSpecificData *tsdPtr = TclGetContLineTable(); if (tsdPtr->objThreadMap == NULL) { tsdPtr->objThreadMap = (Tcl_HashTable *) -- cgit v0.12