summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog31
-rw-r--r--generic/tclIO.c4
-rw-r--r--generic/tclInt.h4
-rw-r--r--mac/tclMacSock.c91
-rw-r--r--unix/tclUnixSock.c48
-rw-r--r--win/tclWinFile.c4
-rw-r--r--win/tclWinSock.c133
7 files changed, 309 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index f4ca8d3..337bd38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);
+}