diff options
-rw-r--r-- | ChangeLog | 31 | ||||
-rw-r--r-- | generic/tclIO.c | 4 | ||||
-rw-r--r-- | generic/tclInt.h | 4 | ||||
-rw-r--r-- | mac/tclMacSock.c | 91 | ||||
-rw-r--r-- | unix/tclUnixSock.c | 48 | ||||
-rw-r--r-- | win/tclWinFile.c | 4 | ||||
-rw-r--r-- | win/tclWinSock.c | 133 |
7 files changed, 309 insertions, 6 deletions
@@ -1,3 +1,34 @@ +2003-04-22 Andreas Kupries <andreask@activestate.com> + + * The changes below fix SF bugs [593810], and [718045]. + + * generic/tclIO.c (Tcl_CutChannel, Tcl_SpliceChannel): + Invoke TclpCutSockChannel and TclpSpliceSockChannel. + + * generic/tclInt.h: Declare TclpCutSockChannel and + TclpSpliceSockChannel. + + * unix/tclUnixSock.c (TclpCutSockChannel, TclpSpliceSockChannel): + Dummy functions, on unix the sockets are _not_ handled + specially. + + * mac/tclMacSock.c (TclpCutSockChannel, TclpSpliceSockChannel): + * win/tclWinSock.c (TclpCutSockChannel, TclpSpliceSockChannel): + New functions to handle socket specific cut/splice operations: + auto-initi of socket system for thread on splice, management of + the module internal per-thread list of sockets, management of + association of sockets with HWNDs for event notification. + + * win/tclWinSock.c (NewSocketInfo): Extended initialization + assignments to cover all items of the structure. During + debugging of the new code mentioned above I found that two + fileds could contain bogus data. + + * win/tclWinFile.c: Added #undef HAVE_NO_FINDEX_ENUMS before + definition because when compiling in debug mode the compiler + complains about a redefinition, and this warning is also treated + as an error. + 2003-04-21 Don Porter <dgp@users.sourceforge.net> * library/tcltest/tcltest.tcl: When the return code of a test does diff --git a/generic/tclIO.c b/generic/tclIO.c index e4e8532..adf6e83 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclIO.c,v 1.67 2003/04/11 17:39:51 andreas_kupries Exp $ + * RCS: @(#) $Id: tclIO.c,v 1.68 2003/04/22 23:20:41 andreas_kupries Exp $ */ #include "tclInt.h" @@ -2411,6 +2411,7 @@ Tcl_CutChannel(chan) statePtr->nextCSPtr = (ChannelState *) NULL; TclpCutFileChannel(chan); + TclpCutSockChannel(chan); } /* @@ -2464,6 +2465,7 @@ Tcl_SpliceChannel(chan) statePtr->managingThread = Tcl_GetCurrentThread (); TclpSpliceFileChannel(chan); + TclpSpliceSockChannel(chan); } /* diff --git a/generic/tclInt.h b/generic/tclInt.h index a4753b9..5df729d 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclInt.h,v 1.124 2003/04/16 23:33:44 dgp Exp $ + * RCS: @(#) $Id: tclInt.h,v 1.125 2003/04/22 23:20:43 andreas_kupries Exp $ */ #ifndef _TCLINT @@ -1747,7 +1747,9 @@ EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions)); EXTERN void TclpCutFileChannel _ANSI_ARGS_((Tcl_Channel chan)); +EXTERN void TclpCutSockChannel _ANSI_ARGS_((Tcl_Channel chan)); EXTERN void TclpSpliceFileChannel _ANSI_ARGS_((Tcl_Channel chan)); +EXTERN void TclpSpliceSockChannel _ANSI_ARGS_((Tcl_Channel chan)); EXTERN void TclpPanic _ANSI_ARGS_(TCL_VARARGS(CONST char *, format)); EXTERN char * TclpReadlink _ANSI_ARGS_((CONST char *fileName, diff --git a/mac/tclMacSock.c b/mac/tclMacSock.c index f272f87..32df000 100644 --- a/mac/tclMacSock.c +++ b/mac/tclMacSock.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: tclMacSock.c,v 1.14 2002/04/08 09:03:17 das Exp $ + * RCS: @(#) $Id: tclMacSock.c,v 1.15 2003/04/22 23:20:43 andreas_kupries Exp $ */ #include "tclInt.h" @@ -2790,3 +2790,92 @@ pascal void NotifyRoutine ( localIcmpMsg = *icmpMsg; } + +/* + *---------------------------------------------------------------------- + * + * TclpCutSockChannel -- + * + * Remove any thread local refs to this channel. See + * Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + +void +TclpCutSockChannel(chan) + Tcl_Channel chan; +{ + ThreadSpecificData *tsdPtr; + TcpState *infoPtr; + TcpState **nextPtrPtr; + int removed = 0; + + if (Tcl_GetChannelType(chan) != &tcpChannelType) + return; + + tsdPtr = TCL_TSD_INIT(&dataKey); + infoPtr = (TcpState *) Tcl_GetChannelInstanceData (chan); + + for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == infoPtr) { + (*nextPtrPtr) = infoPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) + panic("file info ptr not on thread channel list"); + return; +} + +/* + *---------------------------------------------------------------------- + * + * TclpSpliceSockChannel -- + * + * Insert thread local ref for this channel. + * Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + +void +TclpSpliceSockChannel(chan) + Tcl_Channel chan; +{ + ThreadSpecificData *tsdPtr; + TcpState *infoPtr; + + if (Tcl_GetChannelType(chan) != &tcpChannelType) + return; + + InitSockets (); + + tsdPtr = TCL_TSD_INIT(&dataKey); + infoPtr = (TcpState *) Tcl_GetChannelInstanceData (chan); + + infoPtr->nextPtr = tsdPtr->socketList; + tsdPtr->socketList = infoPtr; +} + diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c index 8e5e3b7..91b8096 100644 --- a/unix/tclUnixSock.c +++ b/unix/tclUnixSock.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: tclUnixSock.c,v 1.6 2002/02/27 01:16:43 hobbs Exp $ + * RCS: @(#) $Id: tclUnixSock.c,v 1.7 2003/04/22 23:20:43 andreas_kupries Exp $ */ #include "tcl.h" @@ -148,3 +148,49 @@ TclpHasSockets(interp) { return TCL_OK; } + +/* + *---------------------------------------------------------------------- + * + * TclpCutSockChannel -- + * + * Remove any thread local refs to this channel. See + * Tcl_CutChannel for more info. Dummy definition. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclpCutSockChannel(chan) + Tcl_Channel chan; +{ +} + +/* + *---------------------------------------------------------------------- + * + * TclpSpliceSockChannel -- + * + * Insert thread local ref for this channel. + * Tcl_SpliceChannel for more info. Dummy definition. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclpSpliceSockChannel(chan) + Tcl_Channel chan; +{ +} diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 9a7a8b6..8e52d6d 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.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: tclWinFile.c,v 1.48 2003/04/14 22:54:16 kennykb Exp $ + * RCS: @(#) $Id: tclWinFile.c,v 1.49 2003/04/22 23:20:43 andreas_kupries Exp $ */ //#define _WIN32_WINNT 0x0500 @@ -129,8 +129,10 @@ typedef struct { } DUMMY_REPARSE_BUFFER; #if defined(_MSC_VER) && ( _MSC_VER <= 1100 ) +#undef HAVE_NO_FINDEX_ENUMS #define HAVE_NO_FINDEX_ENUMS #elif !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0400) +#undef HAVE_NO_FINDEX_ENUMS #define HAVE_NO_FINDEX_ENUMS #endif diff --git a/win/tclWinSock.c b/win/tclWinSock.c index b92109b..bca4b72 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.36 2003/01/16 19:02:00 mdejong Exp $ + * RCS: @(#) $Id: tclWinSock.c,v 1.37 2003/04/22 23:20:44 andreas_kupries Exp $ */ #include "tclWinInt.h" @@ -1033,6 +1033,7 @@ NewSocketInfo(socket) ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); infoPtr = (SocketInfo *) ckalloc((unsigned) sizeof(SocketInfo)); + infoPtr->channel = 0; infoPtr->socket = socket; infoPtr->flags = 0; infoPtr->watchEvents = 0; @@ -1040,6 +1041,7 @@ NewSocketInfo(socket) infoPtr->selectEvents = 0; infoPtr->acceptEventCount = 0; infoPtr->acceptProc = NULL; + infoPtr->acceptProcData = NULL; infoPtr->lastError = 0; WaitForSingleObject(tsdPtr->socketListLock, INFINITE); @@ -2656,3 +2658,132 @@ TclWinGetServByName(const char * name, const char * proto) } + +/* + *---------------------------------------------------------------------- + * + * TclpCutSockChannel -- + * + * Remove any thread local refs to this channel. See + * Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + +void +TclpCutSockChannel(chan) + Tcl_Channel chan; /* The channel being removed. Must + * not be referenced in any + * interpreter. */ +{ + ThreadSpecificData *tsdPtr; + SocketInfo *infoPtr; + SocketInfo **nextPtrPtr; + int removed = 0; + + if (Tcl_GetChannelType(chan) != &tcpChannelType) + return; + + /* + * The initializtion of tsdPtr _after_ we have determined that we + * are dealing with socket is necessary. Doing it before causes + * the module to access th tdsPtr when it is not initialized yet, + * causing a lockup. + */ + + tsdPtr = TCL_TSD_INIT(&dataKey); + infoPtr = (SocketInfo *) Tcl_GetChannelInstanceData (chan); + + for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == infoPtr) { + (*nextPtrPtr) = infoPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) { + panic("file info ptr not on thread channel list"); + } + + /* + * Stop notifications for the socket to occur in this thread. + */ + + SendMessage(tsdPtr->hwnd, SOCKET_SELECT, + (WPARAM) UNSELECT, (LPARAM) infoPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TclpSpliceSockChannel -- + * + * Insert thread local ref for this channel. + * Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + +void +TclpSpliceSockChannel(chan) + Tcl_Channel chan; /* The channel being removed. Must + * not be referenced in any + * interpreter. */ +{ + ThreadSpecificData *tsdPtr; + SocketInfo *infoPtr; + + if (Tcl_GetChannelType(chan) != &tcpChannelType) + return; + + /* + * Ensure that socket subsystem is initialized in this thread, or + * else sockets will not work. + */ + + Tcl_MutexLock(&socketMutex); + InitSockets(); + Tcl_MutexUnlock(&socketMutex); + + /* + * The initializtion of tsdPtr _after_ we have determined that we + * are dealing with socket is necessary. Doing it before causes + * the module to access th tdsPtr when it is not initialized yet, + * causing a lockup. + */ + + tsdPtr = TCL_TSD_INIT(&dataKey); + infoPtr = (SocketInfo *) Tcl_GetChannelInstanceData (chan); + + WaitForSingleObject(tsdPtr->socketListLock, INFINITE); + infoPtr->nextPtr = tsdPtr->socketList; + tsdPtr->socketList = infoPtr; + SetEvent(tsdPtr->socketListLock); + + /* + * Ensure that notifications for the socket occur in this thread. + */ + + SendMessage(tsdPtr->hwnd, SOCKET_SELECT, + (WPARAM) SELECT, (LPARAM) infoPtr); +} |