From 6cd14bf5542b934b1b15131087e58f92da9f8a93 Mon Sep 17 00:00:00 2001 From: redman Date: Wed, 26 May 1999 20:24:43 +0000 Subject: generic/tclThreadTest.c: Fix race condition in testthread code. win/tclWinSock.c: Fixed hang in WinNT socket driver, now wakes up the socket thread to check for events that didn't trigger the WSAEvent. --- generic/tclThreadTest.c | 5 ++--- win/tclWinSock.c | 31 +++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/generic/tclThreadTest.c b/generic/tclThreadTest.c index 0acba19..c24b059 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.2 1999/04/16 00:46:54 stanton Exp $ + * RCS: @(#) $Id: tclThreadTest.c,v 1.3 1999/05/26 20:24:43 redman Exp $ */ #include "tclInt.h" @@ -713,10 +713,10 @@ TclThreadSend(interp, id, script, wait) threadEventPtr->event.proc = ThreadEventProc; Tcl_ThreadQueueEvent(threadId, (Tcl_Event *)threadEventPtr, TCL_QUEUE_TAIL); - Tcl_MutexUnlock(&threadMutex); Tcl_ThreadAlert(threadId); if (!wait) { + Tcl_MutexUnlock(&threadMutex); return TCL_OK; } @@ -725,7 +725,6 @@ TclThreadSend(interp, id, script, wait) */ Tcl_ResetResult(interp); - Tcl_MutexLock(&threadMutex); while (resultPtr->result == NULL) { Tcl_ConditionWait(&resultPtr->done, &threadMutex, NULL); } diff --git a/win/tclWinSock.c b/win/tclWinSock.c index 969e2bb..03ded94 100644 --- a/win/tclWinSock.c +++ b/win/tclWinSock.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinSock.c,v 1.9 1999/04/22 20:28:02 redman Exp $ + * RCS: @(#) $Id: tclWinSock.c,v 1.10 1999/05/26 20:24:43 redman Exp $ */ #include "tclWinInt.h" @@ -111,6 +111,13 @@ static struct { #define SOCKET_MESSAGE WM_USER+1 /* + * The following defines the timeout value for the WSAWaitForMultipleEvents + * in milliseconds. + */ + +#define TCL_SOCKET_EVENT_TIMEOUT 100 + +/* * The following structure is used to store the data associated with * each socket. */ @@ -2337,6 +2344,15 @@ TcpGetHandleProc(instanceData, direction, handlePtr) * * SocketThread -- * + * Use a separate thread to check state for the sockets in each + * thread. Using a window isn't the best way, especially if the + * WinSock2 API is available and working. Also, creating N threads + * per socket like the pipe, console, and serial drivers isn't + * very efficient. Currently, all sockets are tied to one event. + * The overhead involved in creating an event for each socket is + * a concern. But, in order to avoid deadlocks, the call to + * WSAWaitForMultipleEvents() needs to timeout to check for + * status changes which haven't been handled (race condition). * * Results: * 0 on success. @@ -2353,7 +2369,7 @@ SocketThread(LPVOID arg) WSAEVENT events[2]; ThreadSpecificData *tsdPtr; DWORD result; - + /* * Find the specified socket on the socket list and update its * eventState flag. @@ -2365,10 +2381,12 @@ SocketThread(LPVOID arg) while (1) { result = (*winSock.WSAWaitForMultipleEvents)(2, events, FALSE, - WSA_INFINITE, FALSE); + TCL_SOCKET_EVENT_TIMEOUT, FALSE); switch (result) { + case WSA_WAIT_TIMEOUT: case (WSA_WAIT_EVENT_0 +1): + /* * A socket event has fired, determine which socket(s) it was * and which thread(s) it came from. @@ -2384,13 +2402,6 @@ SocketThread(LPVOID arg) if (GetSocketState(infoPtr) & infoPtr->watchEvents) { Tcl_ThreadAlert(tsdPtr->threadId); SetEvent(tsdPtr->wakeEvent); - - /* - * Only process one at a time for a given thread, - * so break here. - */ - - break; } } } -- cgit v0.12