diff options
author | sebres <sebres@users.sourceforge.net> | 2024-07-15 01:16:23 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2024-07-15 01:16:23 (GMT) |
commit | a1bb7d4507eeaa0693cc70710d45ac3606f5987c (patch) | |
tree | 995145b06c8943efc0fbec735ab77397e01f0644 | |
parent | b733648e8509bdba457d2f7387bd9029be84d2c2 (diff) | |
download | tcl-a1bb7d4507eeaa0693cc70710d45ac3606f5987c.zip tcl-a1bb7d4507eeaa0693cc70710d45ac3606f5987c.tar.gz tcl-a1bb7d4507eeaa0693cc70710d45ac3606f5987c.tar.bz2 |
fixes memory leak [ae09f6b190ceec31]: properly unload and free InterpLibrary if interpreter gets deleted
-rw-r--r-- | generic/tclLoad.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/generic/tclLoad.c b/generic/tclLoad.c index b14a4a8..6a923fe 100644 --- a/generic/tclLoad.c +++ b/generic/tclLoad.c @@ -783,13 +783,12 @@ Tcl_UnloadObjCmd( */ static int UnloadLibrary( - Tcl_Interp *interp, - Tcl_Interp *target, - LoadedLibrary *libraryPtr, - int keepLibrary, - const char *fullFileName, - int interpExiting -) + Tcl_Interp *interp, + Tcl_Interp *target, + LoadedLibrary *libraryPtr, + int keepLibrary, + const char *fullFileName, + int interpExiting) { int code; InterpLibrary *ipFirstPtr, *ipPtr; @@ -877,24 +876,27 @@ UnloadLibrary( * Remove this library from the interpreter's library cache. */ - ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); - ipPtr = ipFirstPtr; - if (ipPtr->libraryPtr == libraryPtr) { - ipFirstPtr = ipFirstPtr->nextPtr; - } else { - InterpLibrary *ipPrevPtr; - - for (ipPrevPtr = ipPtr; ipPtr != NULL; - ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) { + if (!interpExiting) { + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); + if (ipFirstPtr) { + ipPtr = ipFirstPtr; if (ipPtr->libraryPtr == libraryPtr) { - ipPrevPtr->nextPtr = ipPtr->nextPtr; - break; + ipFirstPtr = ipFirstPtr->nextPtr; + } else { + InterpLibrary *ipPrevPtr; + + for (ipPrevPtr = ipPtr; ipPtr != NULL; + ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) { + if (ipPtr->libraryPtr == libraryPtr) { + ipPrevPtr->nextPtr = ipPtr->nextPtr; + break; + } + } } + ckfree(ipPtr); + Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr); } } - ckfree(ipPtr); - Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr); - if (IsStatic(libraryPtr)) { goto done; @@ -1206,21 +1208,22 @@ TclGetLoadedLibraries( static void LoadCleanupProc( - TCL_UNUSED(ClientData), /* Pointer to first InterpLibrary structure + ClientData clientData, /* Pointer to first InterpLibrary structure * for interp. */ Tcl_Interp *interp) { - InterpLibrary *ipPtr; + InterpLibrary *ipPtr = (InterpLibrary *)clientData, *nextPtr; LoadedLibrary *libraryPtr; - while (1) { - ipPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL); - if (ipPtr == NULL) { - break; - } + do { libraryPtr = ipPtr->libraryPtr; - UnloadLibrary(interp, interp, libraryPtr, 0 ,"", 1); - } + UnloadLibrary(interp, interp, libraryPtr, 0, "", 1); + /* UnloadLibrary doesn't free it by interp delete, so do it here and + * repeat for next. */ + nextPtr = ipPtr->nextPtr; + ckfree(ipPtr); + ipPtr = nextPtr; + } while (ipPtr); } /* |