diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclIO.c | 19 | ||||
-rw-r--r-- | generic/tclIOCmd.c | 16 |
2 files changed, 32 insertions, 3 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 534060b..f198474 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. * - * SCCS: %Z% $Id: tclIO.c,v 1.2 1998/06/09 13:08:16 stanton Exp $ + * SCCS: %Z% $Id: tclIO.c,v 1.3 1998/06/27 18:10:15 welch Exp $ */ #include "tclInt.h" @@ -4519,7 +4519,14 @@ Tcl_NotifyChannel(channel, mask) ChannelHandler *chPtr; NextChannelHandler nh; - Tcl_Preserve((ClientData)chanPtr); + /* + * Prevent the event handler from deleting the channel by incrementing + * the channel's ref count. Case in point: ChannelEventScriptInvoker() + * was evaling a script (owned by the channel) which caused the channel + * to be closed and then the byte codes no longer existed. + */ + + Tcl_RegisterChannel((Tcl_Interp *) NULL, channel); /* * If we are flushing in the background, be sure to call FlushChannel @@ -4566,7 +4573,13 @@ Tcl_NotifyChannel(channel, mask) if (chanPtr->typePtr != NULL) { UpdateInterest(chanPtr); } - Tcl_Release((ClientData)chanPtr); + + /* + * No longer need to protect the channel from being deleted. + * After this point it is unsafe to use the value of "channel". + */ + + Tcl_UnregisterChannel((Tcl_Interp *) NULL, channel); nestedHandlerPtr = nh.nestedHandlerPtr; } diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c index 5640b47..88a299a 100644 --- a/generic/tclIOCmd.c +++ b/generic/tclIOCmd.c @@ -1238,12 +1238,28 @@ AcceptCallbackProc(callbackData, chan, address, port) TclFormatInt(portBuf, port); Tcl_RegisterChannel(interp, chan); + + /* + * Artificially bump the refcount to protect the channel from + * being deleted while the script is being evaluated. + */ + + Tcl_RegisterChannel((Tcl_Interp *) NULL, chan); + result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan), " ", address, " ", portBuf, (char *) NULL); if (result != TCL_OK) { Tcl_BackgroundError(interp); Tcl_UnregisterChannel(interp, chan); } + + /* + * Decrement the artificially bumped refcount. After this it is + * not safe anymore to use "chan", because it may now be deleted. + */ + + Tcl_UnregisterChannel((Tcl_Interp *) NULL, chan); + Tcl_Release((ClientData) interp); Tcl_Release((ClientData) script); } else { |