Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Work in progress plugging thread finalization memory leaks. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | bug-3397515 |
Files: | files | file ages | folders |
SHA1: |
b34df314210e94231fd083d4182025b9 |
User & Date: | dgp 2011-08-29 20:41:02 |
Context
2011-08-30
| ||
15:44 | Prevent segfaults attempting to use thread maps after they've been deleted. Closed-Leaf check-in: a5b9dc7fa4 user: dgp tags: bug-3397515 | |
2011-08-29
| ||
20:41 | Work in progress plugging thread finalization memory leaks. check-in: b34df31421 user: dgp tags: bug-3397515 | |
14:16 | Leak of ReflectedTransformMap. check-in: e993e51faf user: dgp tags: trunk | |
Changes
Changes to generic/tclBasic.c.
︙ | ︙ | |||
1355 1356 1357 1358 1359 1360 1361 | int i; /* * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup, * unless we are exiting. */ | | | 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 | int i; /* * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup, * unless we are exiting. */ if ((iPtr->numLevels > 0) && !TclInExit() && !TclInThreadExit()) { Tcl_Panic("DeleteInterpProc called with active evals"); } /* * The interpreter should already be marked deleted; otherwise how did we * get here? */ |
︙ | ︙ | |||
1478 1479 1480 1481 1482 1483 1484 | } /* * Pop the root frame pointer and finish deleting the global * namespace. The order is important [Bug 1658572]. */ | | > | 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 | } /* * Pop the root frame pointer and finish deleting the global * namespace. The order is important [Bug 1658572]. */ if ((iPtr->framePtr != iPtr->rootFramePtr) && !TclInExit() && !TclInThreadExit()) { Tcl_Panic("DeleteInterpProc: popping rootCallFrame with other frames on top"); } Tcl_PopCallFrame(interp); ckfree(iPtr->rootFramePtr); iPtr->rootFramePtr = NULL; Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr); |
︙ | ︙ | |||
1603 1604 1605 1606 1607 1608 1609 | /* * Location stack for uplevel/eval/... scripts which were passed through * proc arguments. Actually we track all arguments as we do not and cannot * know which arguments will be used as scripts and which will not. */ | | | | 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 | /* * Location stack for uplevel/eval/... scripts which were passed through * proc arguments. Actually we track all arguments as we do not and cannot * know which arguments will be used as scripts and which will not. */ if (iPtr->lineLAPtr->numEntries && !TclInExit() && !TclInThreadExit()) { /* * When the interp goes away we have nothing on the stack, so there * are no arguments, so this table has to be empty. */ Tcl_Panic("Argument location tracking table not empty"); } Tcl_DeleteHashTable(iPtr->lineLAPtr); ckfree((char *) iPtr->lineLAPtr); iPtr->lineLAPtr = NULL; if (iPtr->lineLABCPtr->numEntries && !TclInExit() && !TclInThreadExit()) { /* * When the interp goes away we have nothing on the stack, so there * are no arguments, so this table has to be empty. */ Tcl_Panic("Argument location tracking table not empty"); } |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
894 895 896 897 898 899 900 | *---------------------------------------------------------------------- */ static void DeleteExecStack( ExecStack *esPtr) { | | | 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 | *---------------------------------------------------------------------- */ static void DeleteExecStack( ExecStack *esPtr) { if (esPtr->markerPtr && !cachedInExit && !TclInThreadExit()) { Tcl_Panic("freeing an execStack which is still in use"); } if (esPtr->prevPtr) { esPtr->prevPtr->nextPtr = esPtr->nextPtr; } if (esPtr->nextPtr) { |
︙ | ︙ | |||
930 931 932 933 934 935 936 | tmpPtr = esPtr; esPtr = tmpPtr->prevPtr; DeleteExecStack(tmpPtr); } TclDecrRefCount(eePtr->constants[0]); TclDecrRefCount(eePtr->constants[1]); | | | | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 | tmpPtr = esPtr; esPtr = tmpPtr->prevPtr; DeleteExecStack(tmpPtr); } TclDecrRefCount(eePtr->constants[0]); TclDecrRefCount(eePtr->constants[1]); if (eePtr->callbackPtr && !cachedInExit && !TclInThreadExit()) { Tcl_Panic("Deleting execEnv with pending TEOV callbacks!"); } if (eePtr->corPtr && !cachedInExit &&!TclInThreadExit()) { Tcl_Panic("Deleting execEnv with existing coroutine"); } ckfree(eePtr); } /* *---------------------------------------------------------------------- |
︙ | ︙ |
Changes to generic/tclThreadTest.c.
︙ | ︙ | |||
135 136 137 138 139 140 141 142 143 144 145 146 147 148 | static void ListUpdateInner(ThreadSpecificData *tsdPtr); static int ThreadEventProc(Tcl_Event *evPtr, int mask); static void ThreadErrorProc(Tcl_Interp *interp); static void ThreadFreeProc(ClientData clientData); static int ThreadDeleteEvent(Tcl_Event *eventPtr, ClientData clientData); static void ThreadExitProc(ClientData clientData); extern int Tcltest_Init(Tcl_Interp *interp); /* *---------------------------------------------------------------------- * * TclThread_Init -- * | > | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | static void ListUpdateInner(ThreadSpecificData *tsdPtr); static int ThreadEventProc(Tcl_Event *evPtr, int mask); static void ThreadErrorProc(Tcl_Interp *interp); static void ThreadFreeProc(ClientData clientData); static int ThreadDeleteEvent(Tcl_Event *eventPtr, ClientData clientData); static void ThreadExitProc(ClientData clientData); static void ReleaseInterp(ClientData clientData); extern int Tcltest_Init(Tcl_Interp *interp); /* *---------------------------------------------------------------------- * * TclThread_Init -- * |
︙ | ︙ | |||
322 323 324 325 326 327 328 329 | } case THREAD_EXIT: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } ListRemove(NULL); Tcl_ExitThread(0); | > | | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | } case THREAD_EXIT: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } ListRemove(NULL); Tcl_DeleteInterp(interp); Tcl_ExitThread(0); return TCL_ERROR; case THREAD_ID: if (objc == 2 || objc == 3) { Tcl_Obj *idObj; /* * Check if they want the main thread id or the current thread id. */ |
︙ | ︙ | |||
560 561 562 563 564 565 566 567 568 569 570 571 572 573 | NewTestThread( ClientData clientData) { ThreadCtrl *ctrlPtr = clientData; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); int result; char *threadEvalScript; /* * Initialize the interpreter. This should be more general. */ tsdPtr->interp = Tcl_CreateInterp(); result = Tcl_Init(tsdPtr->interp); | > | 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 | NewTestThread( ClientData clientData) { ThreadCtrl *ctrlPtr = clientData; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); int result; char *threadEvalScript; int fullFinal = TclFullFinalizationRequested(); /* * Initialize the interpreter. This should be more general. */ tsdPtr->interp = Tcl_CreateInterp(); result = Tcl_Init(tsdPtr->interp); |
︙ | ︙ | |||
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | Tcl_MutexUnlock(&threadMutex); /* * Run the script. */ Tcl_Preserve(tsdPtr->interp); result = Tcl_Eval(tsdPtr->interp, threadEvalScript); if (result != TCL_OK) { ThreadErrorProc(tsdPtr->interp); } /* * Clean up. */ ListRemove(tsdPtr); Tcl_Release(tsdPtr->interp); Tcl_DeleteInterp(tsdPtr->interp); Tcl_ExitThread(result); TCL_THREAD_CREATE_RETURN; } /* *------------------------------------------------------------------------ * * ThreadErrorProc -- * * Send a message to the thread willing to hear about errors. | > > > > > > > > > > > > > > > | 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | Tcl_MutexUnlock(&threadMutex); /* * Run the script. */ Tcl_Preserve(tsdPtr->interp); if (fullFinal) { Tcl_CreateThreadExitHandler(ReleaseInterp, tsdPtr->interp); } result = Tcl_Eval(tsdPtr->interp, threadEvalScript); if (fullFinal) { Tcl_DeleteThreadExitHandler(ReleaseInterp, tsdPtr->interp); } if (result != TCL_OK) { ThreadErrorProc(tsdPtr->interp); } /* * Clean up. */ ListRemove(tsdPtr); Tcl_Release(tsdPtr->interp); Tcl_DeleteInterp(tsdPtr->interp); Tcl_ExitThread(result); TCL_THREAD_CREATE_RETURN; } static void ReleaseInterp( ClientData clientData) { Tcl_Interp *interp = (Tcl_Interp *) clientData; Tcl_Release(interp); } /* *------------------------------------------------------------------------ * * ThreadErrorProc -- * * Send a message to the thread willing to hear about errors. |
︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 | if (interp == NULL) { code = TCL_ERROR; result = "no target interp!"; errorCode = "THREAD"; errorInfo = ""; } else { Tcl_Preserve(interp); Tcl_ResetResult(interp); Tcl_CreateThreadExitHandler(ThreadFreeProc, threadEventPtr->script); code = Tcl_GlobalEval(interp, threadEventPtr->script); Tcl_DeleteThreadExitHandler(ThreadFreeProc, threadEventPtr->script); if (code != TCL_OK) { errorCode = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY); errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); } else { errorCode = errorInfo = NULL; } result = Tcl_GetStringResult(interp); | > > > > > > > > | 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | if (interp == NULL) { code = TCL_ERROR; result = "no target interp!"; errorCode = "THREAD"; errorInfo = ""; } else { int fullFinal = TclFullFinalizationRequested(); Tcl_Preserve(interp); Tcl_ResetResult(interp); if (fullFinal) { Tcl_CreateThreadExitHandler(ReleaseInterp, tsdPtr->interp); } Tcl_CreateThreadExitHandler(ThreadFreeProc, threadEventPtr->script); code = Tcl_GlobalEval(interp, threadEventPtr->script); Tcl_DeleteThreadExitHandler(ThreadFreeProc, threadEventPtr->script); if (fullFinal) { Tcl_DeleteThreadExitHandler(ReleaseInterp, tsdPtr->interp); } if (code != TCL_OK) { errorCode = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY); errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); } else { errorCode = errorInfo = NULL; } result = Tcl_GetStringResult(interp); |
︙ | ︙ |