summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2024-07-15 01:16:23 (GMT)
committersebres <sebres@users.sourceforge.net>2024-07-15 01:16:23 (GMT)
commita1bb7d4507eeaa0693cc70710d45ac3606f5987c (patch)
tree995145b06c8943efc0fbec735ab77397e01f0644
parentb733648e8509bdba457d2f7387bd9029be84d2c2 (diff)
downloadtcl-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.c63
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);
}
/*