diff options
Diffstat (limited to 'mac/tclMacSock.c')
-rw-r--r-- | mac/tclMacSock.c | 184 |
1 files changed, 103 insertions, 81 deletions
diff --git a/mac/tclMacSock.c b/mac/tclMacSock.c index fe276f1..e192560 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. * - * SCCS: @(#) tclMacSock.c 1.59 97/10/09 18:24:42 + * SCCS: @(#) tclMacSock.c 1.63 98/02/19 15:32:22 */ #include "tclInt.h" @@ -240,11 +240,15 @@ static PortInfo portServices[] = { {NULL, 0}, }; -/* - * Every open socket has an entry on the following list. - */ +typedef struct ThreadSpecificData { + /* + * Every open socket has an entry on the following list. + */ + + TcpState *socketList; +} ThreadSpecificData; -static TcpState *socketList = NULL; +static Tcl_ThreadDataKey dataKey; /* * Globals for holding information about OS support for sockets. @@ -284,64 +288,77 @@ InitSockets() ParamBlockRec pb; OSErr err; long response; + ThreadSpecificData *tsdPtr; + + if (! initialized) { + /* + * Do process wide initialization. + */ - initialized = 1; - Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL); - - if (Gestalt(gestaltMacTCPVersion, &response) == noErr) { - hasSockets = true; - } else { - hasSockets = false; - } - - if (!hasSockets) { - return; - } - - /* - * Load MacTcp driver and name server resolver. - */ - - - pb.ioParam.ioCompletion = 0L; - pb.ioParam.ioNamePtr = "\p.IPP"; - pb.ioParam.ioPermssn = fsCurPerm; - err = PBOpenSync(&pb); - if (err != noErr) { - hasSockets = 0; - return; - } - driverRefNum = pb.ioParam.ioRefNum; - - socketBufferSize = GetBufferSize(); - err = OpenResolver(NULL); - if (err != noErr) { - hasSockets = 0; - return; + initialized = 1; + + if (Gestalt(gestaltMacTCPVersion, &response) == noErr) { + hasSockets = true; + } else { + hasSockets = false; + } + + if (!hasSockets) { + return; + } + + /* + * Load MacTcp driver and name server resolver. + */ + + + pb.ioParam.ioCompletion = 0L; + pb.ioParam.ioNamePtr = "\p.IPP"; + pb.ioParam.ioPermssn = fsCurPerm; + err = PBOpenSync(&pb); + if (err != noErr) { + hasSockets = 0; + return; + } + driverRefNum = pb.ioParam.ioRefNum; + + socketBufferSize = GetBufferSize(); + err = OpenResolver(NULL); + if (err != noErr) { + hasSockets = 0; + return; + } + + GetCurrentProcess(&applicationPSN); + /* + * Create UPP's for various callback routines. + */ + + resultUPP = NewResultProc(DNRCompletionRoutine); + completeUPP = NewTCPIOCompletionProc(IOCompletionRoutine); + closeUPP = NewTCPIOCompletionProc(CloseCompletionRoutine); + + /* + * Install an ExitToShell patch. We use this patch instead + * of the Tcl exit mechanism because we need to ensure that + * these routines are cleaned up even if we crash or are forced + * to quit. There are some circumstances when the Tcl exit + * handlers may not fire. + */ + + TclMacInstallExitToShellPatch(CleanUpExitProc); } - GetCurrentProcess(&applicationPSN); - /* - * Create UPP's for various callback routines. - */ - - resultUPP = NewResultProc(DNRCompletionRoutine); - completeUPP = NewTCPIOCompletionProc(IOCompletionRoutine); - closeUPP = NewTCPIOCompletionProc(CloseCompletionRoutine); - /* - * Install an ExitToShell patch. We use this patch instead - * of the Tcl exit mechanism because we need to ensure that - * these routines are cleaned up even if we crash or are forced - * to quit. There are some circumstances when the Tcl exit - * handlers may not fire. + * Do per-thread initialization. */ - TclMacInstallExitToShellPatch(CleanUpExitProc); - - Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); - - initialized = 1; + tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); + if (tsdPtr == NULL) { + tsdPtr->socketList = NULL; + Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); + Tcl_CreateThreadExitHandler(SocketExitHandler, (ClientData) NULL); + } } /* @@ -370,13 +387,12 @@ SocketExitHandler( /* CleanUpExitProc(); TclMacDeleteExitToShellPatch(CleanUpExitProc); */ } - initialized = 0; } /* *---------------------------------------------------------------------- * - * TclHasSockets -- + * TclpHasSockets -- * * This function determines whether sockets are available on the * current system and returns an error in interp if they are not. @@ -393,12 +409,10 @@ SocketExitHandler( */ int -TclHasSockets( +TclpHasSockets( Tcl_Interp *interp) /* Interp for error messages. */ { - if (!initialized) { - InitSockets(); - } + InitSockets(); if (hasSockets) { return TCL_OK; @@ -434,6 +448,7 @@ SocketSetupProc( { TcpState *statePtr; Tcl_Time blockTime = { 0, 0 }; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; @@ -443,7 +458,7 @@ SocketSetupProc( * Check to see if there is a ready socket. If so, poll. */ - for (statePtr = socketList; statePtr != NULL; + for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if (statePtr->flags & TCP_RELEASE) { continue; @@ -480,6 +495,7 @@ SocketCheckProc( TcpState *statePtr; SocketEvent *evPtr; TcpState dummyState; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; @@ -491,7 +507,7 @@ SocketCheckProc( * events). */ - for (statePtr = socketList; statePtr != NULL; + for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { /* * Check to see if this socket is dead and needs to be cleaned @@ -1470,6 +1486,7 @@ NewSocketInfo( StreamPtr tcpStream) { TcpState *statePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState)); statePtr->tcpStream = tcpStream; @@ -1479,8 +1496,8 @@ NewSocketInfo( statePtr->watchMask = 0; statePtr->acceptProc = (Tcl_TcpAcceptProc *) NULL; statePtr->acceptProcData = (ClientData) NULL; - statePtr->nextPtr = socketList; - socketList = statePtr; + statePtr->nextPtr = tsdPtr->socketList; + tsdPtr->socketList = statePtr; return statePtr; } @@ -1505,11 +1522,13 @@ static void FreeSocketInfo( TcpState *statePtr) /* The state pointer to free. */ { - if (statePtr == socketList) { - socketList = statePtr->nextPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (statePtr == tsdPtr->socketList) { + tsdPtr->socketList = statePtr->nextPtr; } else { TcpState *p; - for (p = socketList; p != NULL; p = p->nextPtr) { + for (p = tsdPtr->socketList; p != NULL; p = p->nextPtr) { if (p->nextPtr == statePtr) { p->nextPtr = statePtr->nextPtr; break; @@ -1542,7 +1561,7 @@ Tcl_MakeTcpClientChannel( TcpState *statePtr; char channelName[20]; - if (TclHasSockets(NULL) != TCL_OK) { + if (TclpHasSockets(NULL) != TCL_OK) { return NULL; } @@ -1769,7 +1788,7 @@ Tcl_OpenTcpClient( TcpState *statePtr; char channelName[20]; - if (TclHasSockets(interp) != TCL_OK) { + if (TclpHasSockets(interp) != TCL_OK) { return NULL; } @@ -1820,7 +1839,7 @@ Tcl_OpenTcpServer( TcpState *statePtr; char channelName[20]; - if (TclHasSockets(interp) != TCL_OK) { + if (TclpHasSockets(interp) != TCL_OK) { return NULL; } @@ -1875,6 +1894,7 @@ SocketEventProc( TcpState *statePtr; SocketEvent *eventPtr = (SocketEvent *) evPtr; int mask = 0; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; @@ -1884,7 +1904,7 @@ SocketEventProc( * Find the specified socket on the socket list. */ - for (statePtr = socketList; statePtr != NULL; + for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if ((statePtr == eventPtr->statePtr) && (statePtr->tcpStream == eventPtr->tcpStream)) { @@ -2126,7 +2146,7 @@ Tcl_GetHostName() return hostname; } - if (TclHasSockets(NULL) == TCL_OK) { + if (TclpHasSockets(NULL) == TCL_OK) { err = GetLocalAddress(&ourAddress); if (err == noErr) { /* @@ -2266,10 +2286,11 @@ CleanUpExitProc() { TCPiopb exitPB; TcpState *statePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - while (socketList != NULL) { - statePtr = socketList; - socketList = statePtr->nextPtr; + while (tsdPtr->socketList != NULL) { + statePtr = tsdPtr->socketList; + tsdPtr->socketList = statePtr->nextPtr; /* * Close and Release the connection. @@ -2321,7 +2342,7 @@ GetHostFromString( EventRecord dummy; DNRState dnrState; - if (TclHasSockets(NULL) != TCL_OK) { + if (TclpHasSockets(NULL) != TCL_OK) { return 0; } @@ -2536,7 +2557,7 @@ GetBufferSize() * Results: * A standard Tcl result. On success, the port number is * returned in portPtr. On failure, an error message is left in - * interp->result. + * the interp's result. * * Side effects: * None. @@ -2604,8 +2625,9 @@ static void ClearZombieSockets() { TcpState *statePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - for (statePtr = socketList; statePtr != NULL; + for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if (statePtr->flags & TCP_RELEASE) { SocketFreeProc(statePtr); |