summaryrefslogtreecommitdiffstats
path: root/generic/tclThreadTest.c
diff options
context:
space:
mode:
authorhobbs <hobbs>1999-10-21 02:16:21 (GMT)
committerhobbs <hobbs>1999-10-21 02:16:21 (GMT)
commit255b6f78419e20a2954baaab97b26182a4b27c76 (patch)
tree4f65ebbb53559917f7b5085067635040cae62b80 /generic/tclThreadTest.c
parentd5139c797f55bb15e8fe74bdd46ba58a6930794b (diff)
downloadtcl-255b6f78419e20a2954baaab97b26182a4b27c76.zip
tcl-255b6f78419e20a2954baaab97b26182a4b27c76.tar.gz
tcl-255b6f78419e20a2954baaab97b26182a4b27c76.tar.bz2
* unix/tclUnixNotfy.c: fixed event/io threading problems by
making triggerPipe non-blocking * library/tcltest1.0/tcltest.tcl: * generic/tclThreadTest.c: fixed mem leaks in threads * generic/tclResult.c: fixed Tcl_AppendResultVA so it only iterates once over the va_list (avoiding a memcpy of it, which is not portable). * generic/regc_color.c: fixed mem leak and assertion, from HS * generic/tclCompile.c: removed savedChar trick that appeared to be causing a segv when the literal table was released * tests/string.test: * generic/tclCmdMZ.c: fixed [string index] to return ByteArrayObj when indexing into one (test case string-5.16) [Bug: 2871]
Diffstat (limited to 'generic/tclThreadTest.c')
-rw-r--r--generic/tclThreadTest.c101
1 files changed, 89 insertions, 12 deletions
diff --git a/generic/tclThreadTest.c b/generic/tclThreadTest.c
index c24b059..113f327 100644
--- a/generic/tclThreadTest.c
+++ b/generic/tclThreadTest.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclThreadTest.c,v 1.3 1999/05/26 20:24:43 redman Exp $
+ * RCS: @(#) $Id: tclThreadTest.c,v 1.4 1999/10/21 02:16:22 hobbs Exp $
*/
#include "tclInt.h"
@@ -135,6 +135,9 @@ static void ListRemove _ANSI_ARGS_((ThreadSpecificData *tsdPtr));
static void ListUpdateInner _ANSI_ARGS_((ThreadSpecificData *tsdPtr));
static int ThreadEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int mask));
static void ThreadErrorProc _ANSI_ARGS_((Tcl_Interp *interp));
+static void ThreadFreeProc _ANSI_ARGS_((ClientData clientData));
+static int ThreadDeleteEvent _ANSI_ARGS_((Tcl_Event *eventPtr,
+ ClientData clientData));
static void ThreadExitProc _ANSI_ARGS_((ClientData clientData));
@@ -351,8 +354,7 @@ TclCreateThread(interp, script)
ThreadCtrl ctrl;
Tcl_ThreadId id;
- ctrl.script = (char*)ckalloc( strlen(script) + 1 );
- strcpy(ctrl.script, script);
+ ctrl.script = (char *) script;
ctrl.condWait = NULL;
ctrl.flags = 0;
@@ -413,10 +415,8 @@ NewThread(clientData)
{
ThreadCtrl *ctrlPtr = (ThreadCtrl*)clientData;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- ThreadCtrl ctrl;
int result;
-
- ctrl = *ctrlPtr;
+ char *threadEvalScript;
/*
* Initialize the interpreter. This should be more general.
@@ -432,7 +432,14 @@ NewThread(clientData)
Tcl_MutexLock(&threadMutex);
ListUpdateInner(tsdPtr);
- Tcl_CreateThreadExitHandler(ThreadExitProc, NULL);
+ /*
+ * We need to keep a pointer to the alloc'ed mem of the script
+ * we are eval'ing, for the case that we exit during evaluation
+ */
+ threadEvalScript = (char *) ckalloc(strlen(ctrlPtr->script)+1);
+ strcpy(threadEvalScript, ctrlPtr->script);
+
+ Tcl_CreateThreadExitHandler(ThreadExitProc, (ClientData) threadEvalScript);
/*
* Notify the parent we are alive.
@@ -446,7 +453,7 @@ NewThread(clientData)
*/
Tcl_Preserve((ClientData) tsdPtr->interp);
- result = Tcl_Eval(tsdPtr->interp, ctrl.script);
+ result = Tcl_Eval(tsdPtr->interp, threadEvalScript);
if (result != TCL_OK) {
ThreadErrorProc(tsdPtr->interp);
}
@@ -456,7 +463,6 @@ NewThread(clientData)
*/
ListRemove(tsdPtr);
- ckfree((char*)ctrl.script);
Tcl_Release((ClientData) tsdPtr->interp);
Tcl_DeleteInterp(tsdPtr->interp);
Tcl_ExitThread(result);
@@ -676,7 +682,7 @@ TclThreadSend(interp, id, script, wait)
threadEventPtr->script = ckalloc(strlen(script) + 1);
strcpy(threadEventPtr->script, script);
if (!wait) {
- threadEventPtr->resultPtr = NULL;
+ resultPtr = threadEventPtr->resultPtr = NULL;
} else {
resultPtr = (ThreadEventResult *) ckalloc(sizeof(ThreadEventResult));
threadEventPtr->resultPtr = resultPtr;
@@ -802,7 +808,11 @@ ThreadEventProc(evPtr, mask)
} else {
Tcl_Preserve((ClientData) interp);
Tcl_ResetResult(interp);
+ Tcl_CreateThreadExitHandler(ThreadFreeProc,
+ (ClientData) threadEventPtr->script);
code = Tcl_GlobalEval(interp, threadEventPtr->script);
+ Tcl_DeleteThreadExitHandler(ThreadFreeProc,
+ (ClientData) threadEventPtr->script);
result = Tcl_GetStringResult(interp);
if (code != TCL_OK) {
errorCode = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY);
@@ -837,6 +847,65 @@ ThreadEventProc(evPtr, mask)
/*
*------------------------------------------------------------------------
*
+ * ThreadFreeProc --
+ *
+ * This is called from when we are exiting and memory needs
+ * to be freed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Clears up mem specified in ClientData
+ *
+ *------------------------------------------------------------------------
+ */
+ /* ARGSUSED */
+void
+ThreadFreeProc(clientData)
+ ClientData clientData;
+{
+ if (clientData) {
+ ckfree((char *) clientData);
+ }
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * ThreadDeleteEvent --
+ *
+ * This is called from the ThreadExitProc to delete memory related
+ * to events that we put on the queue.
+ *
+ * Results:
+ * 1 it was our event and we want it removed, 0 otherwise.
+ *
+ * Side effects:
+ * It cleans up our events in the event queue for this thread.
+ *
+ *------------------------------------------------------------------------
+ */
+ /* ARGSUSED */
+int
+ThreadDeleteEvent(eventPtr, clientData)
+ Tcl_Event *eventPtr; /* Really ThreadEvent */
+ ClientData clientData; /* dummy */
+{
+ if (eventPtr->proc == ThreadEventProc) {
+ ckfree((char *) ((ThreadEvent *) eventPtr)->script);
+ return 1;
+ }
+ /*
+ * If it was NULL, we were in the middle of servicing the event
+ * and it should be removed
+ */
+ return (eventPtr->proc == NULL);
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
* ThreadExitProc --
*
* This is called when the thread exits.
@@ -852,13 +921,21 @@ ThreadEventProc(evPtr, mask)
*/
/* ARGSUSED */
void
-ThreadExitProc(dummy)
- ClientData dummy;
+ThreadExitProc(clientData)
+ ClientData clientData;
{
+ char *threadEvalScript = (char *) clientData;
ThreadEventResult *resultPtr, *nextPtr;
Tcl_ThreadId self = Tcl_GetCurrentThread();
Tcl_MutexLock(&threadMutex);
+
+ if (threadEvalScript) {
+ ckfree((char *) threadEvalScript);
+ threadEvalScript = NULL;
+ }
+ Tcl_DeleteEvents((Tcl_EventDeleteProc *)ThreadDeleteEvent, NULL);
+
for (resultPtr = resultList ; resultPtr ; resultPtr = nextPtr) {
nextPtr = resultPtr->nextPtr;
if (resultPtr->srcThreadId == self) {