ADDED ChangeLog Index: ChangeLog ================================================================== --- /dev/null +++ ChangeLog @@ -0,0 +1,10 @@ +2000-05-31 Brent Welch + + * tls.c: Change the ChannelHandler to be registered on the main + channel as oppsed to the "parent", or superceeded, channel. This + is because the socket driver notifies the main channel, and there are + times with the main channel gets closed, but the superceded one + is not yet closed. If the channel handler gets triggered in this + half-open state it is associated with the superceeded channedl, but + uses its private pointer to the main channel, which is mostly destroyed. + * Eliminated the redundant call to Tcl_NotifyChannel from TlsWatchProc Index: tlsIO.c ================================================================== --- tlsIO.c +++ tlsIO.c @@ -1,9 +1,9 @@ /* * Copyright (C) 1997-2000 Matt Newman * - * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.2 2000/01/20 01:52:18 aborr Exp $ + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.3 2000/05/31 21:24:24 welch Exp $ * * TLS (aka SSL) Channel - can be layered on any bi-directional * Tcl_Channel (Note: Requires Trf Core Patch) * * This was built from scratch based upon observation of OpenSSL 0.9.2B @@ -125,22 +125,22 @@ CloseProc(ClientData instanceData, /* The socket to close. */ Tcl_Interp *interp) /* For error reporting - unused. */ { State *statePtr = (State *) instanceData; #if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 2 - Tcl_Channel parent = Tls_GetParent(statePtr); + Tcl_Channel chanPtr = Tls_GetParent(statePtr); #else - Tcl_Channel parent = statePtr->self; /* 'self' already refers to our parent */ + Tcl_Channel chanPtr = statePtr->self; /* 'self' already refers to our parent */ #endif dprintf(stderr,"\nCloseProc(0x%x)", statePtr); /* - * Remove event handler to underlying channel, this could + * Remove event handler to the channel, this could * be because we are closing for real, or being "unstacked". */ - Tcl_DeleteChannelHandler( parent, + Tcl_DeleteChannelHandler( chanPtr, ChannelHandler, (ClientData) statePtr); if (statePtr->timer != (Tcl_TimerToken)NULL) { Tcl_DeleteTimerHandler (statePtr->timer); statePtr->timer = (Tcl_TimerToken)NULL; @@ -384,25 +384,37 @@ int mask) /* Events of interest; an OR-ed * combination of TCL_READABLE, * TCL_WRITABLE and TCL_EXCEPTION. */ { State *statePtr = (State *) instanceData; +#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 2 + Tcl_Channel chanPtr = Tls_GetParent(statePtr); +#else + /* + * We set up the channel handler on the main channel, not the + * hidden channel. The main channel gets notified by the underlying + * drivers, so we don't need to put the handler anywhere else. + * Also, because our state refers to the main channel, it is only + * safe to have our handler registered on that same channel. + */ + Tcl_Channel chanPtr = statePtr->self; +#endif if (mask == statePtr->watchMask) return; if (statePtr->watchMask) { /* - * Remove event handler to underlying channel, this could + * Remove event handler to the channel, this could * be because we are closing for real, or being "unstacked". */ - Tcl_DeleteChannelHandler( Tls_GetParent(statePtr), ChannelHandler, (ClientData) statePtr); + Tcl_DeleteChannelHandler( chanPtr, ChannelHandler, (ClientData) statePtr); } statePtr->watchMask = mask; if (statePtr->watchMask) { /* Setup active monitor for events on underlying Channel */ - Tcl_CreateChannelHandler( Tls_GetParent(statePtr), statePtr->watchMask, + Tcl_CreateChannelHandler( chanPtr, statePtr->watchMask, ChannelHandler, (ClientData) statePtr); } } /* @@ -479,11 +491,17 @@ mask |= TCL_WRITABLE; } if (BIO_pending(statePtr->bio)) { mask |= TCL_READABLE; } +#ifdef notdef + /* + * Tcl_NotifyChannel already runs through the list of stacked + * channels doing chained notifications. No need to do this. + */ Tcl_NotifyChannel(statePtr->self, mask); +#endif if (statePtr->timer != (Tcl_TimerToken)NULL) { Tcl_DeleteTimerHandler(statePtr->timer); statePtr->timer = (Tcl_TimerToken)NULL; }