Skip to content

Commit a1bb7d4

Browse files
committed
fixes memory leak [ae09f6b190ceec31]: properly unload and free InterpLibrary if interpreter gets deleted
1 parent b733648 commit a1bb7d4

File tree

1 file changed

+33
-30
lines changed

1 file changed

+33
-30
lines changed

generic/tclLoad.c

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -783,13 +783,12 @@ Tcl_UnloadObjCmd(
783783
*/
784784
static int
785785
UnloadLibrary(
786-
Tcl_Interp *interp,
787-
Tcl_Interp *target,
788-
LoadedLibrary *libraryPtr,
789-
int keepLibrary,
790-
const char *fullFileName,
791-
int interpExiting
792-
)
786+
Tcl_Interp *interp,
787+
Tcl_Interp *target,
788+
LoadedLibrary *libraryPtr,
789+
int keepLibrary,
790+
const char *fullFileName,
791+
int interpExiting)
793792
{
794793
int code;
795794
InterpLibrary *ipFirstPtr, *ipPtr;
@@ -877,24 +876,27 @@ UnloadLibrary(
877876
* Remove this library from the interpreter's library cache.
878877
*/
879878

880-
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
881-
ipPtr = ipFirstPtr;
882-
if (ipPtr->libraryPtr == libraryPtr) {
883-
ipFirstPtr = ipFirstPtr->nextPtr;
884-
} else {
885-
InterpLibrary *ipPrevPtr;
886-
887-
for (ipPrevPtr = ipPtr; ipPtr != NULL;
888-
ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) {
879+
if (!interpExiting) {
880+
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
881+
if (ipFirstPtr) {
882+
ipPtr = ipFirstPtr;
889883
if (ipPtr->libraryPtr == libraryPtr) {
890-
ipPrevPtr->nextPtr = ipPtr->nextPtr;
891-
break;
884+
ipFirstPtr = ipFirstPtr->nextPtr;
885+
} else {
886+
InterpLibrary *ipPrevPtr;
887+
888+
for (ipPrevPtr = ipPtr; ipPtr != NULL;
889+
ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) {
890+
if (ipPtr->libraryPtr == libraryPtr) {
891+
ipPrevPtr->nextPtr = ipPtr->nextPtr;
892+
break;
893+
}
894+
}
892895
}
896+
ckfree(ipPtr);
897+
Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr);
893898
}
894899
}
895-
ckfree(ipPtr);
896-
Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr);
897-
898900

899901
if (IsStatic(libraryPtr)) {
900902
goto done;
@@ -1206,21 +1208,22 @@ TclGetLoadedLibraries(
12061208

12071209
static void
12081210
LoadCleanupProc(
1209-
TCL_UNUSED(ClientData), /* Pointer to first InterpLibrary structure
1211+
ClientData clientData, /* Pointer to first InterpLibrary structure
12101212
* for interp. */
12111213
Tcl_Interp *interp)
12121214
{
1213-
InterpLibrary *ipPtr;
1215+
InterpLibrary *ipPtr = (InterpLibrary *)clientData, *nextPtr;
12141216
LoadedLibrary *libraryPtr;
12151217

1216-
while (1) {
1217-
ipPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL);
1218-
if (ipPtr == NULL) {
1219-
break;
1220-
}
1218+
do {
12211219
libraryPtr = ipPtr->libraryPtr;
1222-
UnloadLibrary(interp, interp, libraryPtr, 0 ,"", 1);
1223-
}
1220+
UnloadLibrary(interp, interp, libraryPtr, 0, "", 1);
1221+
/* UnloadLibrary doesn't free it by interp delete, so do it here and
1222+
* repeat for next. */
1223+
nextPtr = ipPtr->nextPtr;
1224+
ckfree(ipPtr);
1225+
ipPtr = nextPtr;
1226+
} while (ipPtr);
12241227
}
12251228

12261229
/*

0 commit comments

Comments
 (0)