Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Further fix for issue [ea69b0258a9833cb], crash when using a channel transformation on TCP client socket. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | core-8-branch |
Files: | files | file ages | folders |
SHA3-256: |
294e0130dcff79a3277e55277ff75ccd |
User & Date: | pooryorick 2023-03-15 09:25:15.098 |
References
2023-03-15
| ||
11:43 | • Ticket [ea69b0258a] Crash when using a channel transformation on TCP client socket status still Pending with 3 other changes artifact: 5e9fa93a3d user: pooryorick | |
Context
2023-03-15
| ||
09:32 | Merge-mark. @nathan, please do forward merges from core-8-6-branch -> core-8-branch -> trunk. Fossil... check-in: 167eb8706f user: jan.nijtmans tags: core-8-branch | |
09:25 | Further fix for issue [ea69b0258a9833cb], crash when using a channel transformation on TCP client so... check-in: 294e0130dc user: pooryorick tags: core-8-branch | |
08:42 | Further fix for issue [ea69b0258a9833cb], crash when using a channel transformation on TCP client so... Closed-Leaf check-in: 26a20919fb user: pooryorick tags: core-8-branch-bug-ea69b0258a9833cb6 | |
2023-03-14
| ||
10:30 | Since "unicode" is deprecated, use "utf-16" in testcases. Otherwise -DTCL_NO_DEPRECATED build fails. check-in: f21f27b7c5 user: jan.nijtmans tags: core-8-branch | |
Changes
Changes to generic/tclIO.c.
︙ | ︙ | |||
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | static int CheckChannelErrors(ChannelState *statePtr, int direction); static int CheckForDeadChannel(Tcl_Interp *interp, ChannelState *statePtr); static void CheckForStdChannelsBeingClosed(Tcl_Channel chan); static void CleanupChannelHandlers(Tcl_Interp *interp, Channel *chanPtr); static int CloseChannel(Tcl_Interp *interp, Channel *chanPtr, int errorCode); static int CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr, int errorCode, int flags); static int CloseWrite(Tcl_Interp *interp, Channel *chanPtr); static void CommonGetsCleanup(Channel *chanPtr); static int CopyData(CopyState *csPtr, int mask); static int MoveBytes(CopyState *csPtr); static void MBCallback(CopyState *csPtr, Tcl_Obj *errObj); static void MBError(CopyState *csPtr, int mask, int errorCode); static int MBRead(CopyState *csPtr); static int MBWrite(CopyState *csPtr); static void MBEvent(void *clientData, int mask); | > > | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | static int CheckChannelErrors(ChannelState *statePtr, int direction); static int CheckForDeadChannel(Tcl_Interp *interp, ChannelState *statePtr); static void CheckForStdChannelsBeingClosed(Tcl_Channel chan); static void CleanupChannelHandlers(Tcl_Interp *interp, Channel *chanPtr); static void CleanupTimerHandler(ChannelState *statePtr); static int CloseChannel(Tcl_Interp *interp, Channel *chanPtr, int errorCode); static int CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr, int errorCode, int flags); static int CloseWrite(Tcl_Interp *interp, Channel *chanPtr); static void CommonGetsCleanup(Channel *chanPtr); static int CopyData(CopyState *csPtr, int mask); static void DeleteTimerHandler(ChannelState *statePtr); static int MoveBytes(CopyState *csPtr); static void MBCallback(CopyState *csPtr, Tcl_Obj *errObj); static void MBError(CopyState *csPtr, int mask, int errorCode); static int MBRead(CopyState *csPtr); static int MBWrite(CopyState *csPtr); static void MBEvent(void *clientData, int mask); |
︙ | ︙ | |||
1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 | statePtr->inQueueHead = NULL; statePtr->inQueueTail = NULL; statePtr->chPtr = NULL; statePtr->interestMask = 0; statePtr->scriptRecordPtr = NULL; statePtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE; statePtr->timer = NULL; statePtr->csPtrR = NULL; statePtr->csPtrW = NULL; statePtr->outputStage = NULL; /* * As we are creating the channel, it is obviously the top for now. */ | > | 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 | statePtr->inQueueHead = NULL; statePtr->inQueueTail = NULL; statePtr->chPtr = NULL; statePtr->interestMask = 0; statePtr->scriptRecordPtr = NULL; statePtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE; statePtr->timer = NULL; statePtr->timerChanPtr = NULL; statePtr->csPtrR = NULL; statePtr->csPtrW = NULL; statePtr->outputStage = NULL; /* * As we are creating the channel, it is obviously the top for now. */ |
︙ | ︙ | |||
3183 3184 3185 3186 3187 3188 3189 3190 | Tcl_SetErrno(errorCode); } } /* * Cancel any outstanding timer. */ | > < | 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 | Tcl_SetErrno(errorCode); } } /* * Cancel any outstanding timer. */ DeleteTimerHandler(statePtr); /* * Mark the channel as deleted by clearing the type structure. */ if (chanPtr->downChanPtr != NULL) { Channel *downChanPtr = chanPtr->downChanPtr; |
︙ | ︙ | |||
3536 3537 3538 3539 3540 3541 3542 | } Tcl_ClearChannelHandlers(chan); /* * Cancel any outstanding timer. */ | | | 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 | } Tcl_ClearChannelHandlers(chan); /* * Cancel any outstanding timer. */ DeleteTimerHandler(statePtr); /* * Invoke the registered close callbacks and delete their records. */ while (statePtr->closeCbPtr != NULL) { cbPtr = statePtr->closeCbPtr; |
︙ | ︙ | |||
4011 4012 4013 4014 4015 4016 4017 | chanPtr = (Channel *) channel; statePtr = chanPtr->state; chanPtr = statePtr->topChanPtr; /* * Cancel any outstanding timer. */ | < | | 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 | chanPtr = (Channel *) channel; statePtr = chanPtr->state; chanPtr = statePtr->topChanPtr; /* * Cancel any outstanding timer. */ DeleteTimerHandler(statePtr); /* * Remove any references to channel handlers for this channel that may be * about to be invoked. */ for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != NULL; |
︙ | ︙ | |||
8801 8802 8803 8804 8805 8806 8807 8808 | * testsuite on all of them. */ mask &= ~TCL_EXCEPTION; if (!statePtr->timer) { TclChannelPreserve((Tcl_Channel)chanPtr); statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, | > | > | 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 | * testsuite on all of them. */ mask &= ~TCL_EXCEPTION; if (!statePtr->timer) { TclChannelPreserve((Tcl_Channel)chanPtr); statePtr->timerChanPtr = chanPtr; statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc, chanPtr); } } } if (!statePtr->timer && mask & TCL_WRITABLE && GotFlag(statePtr, CHANNEL_NONBLOCKING)) { TclChannelPreserve((Tcl_Channel)chanPtr); statePtr->timerChanPtr = chanPtr; statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); } ChanWatch(chanPtr, mask); } |
︙ | ︙ | |||
8842 8843 8844 8845 8846 8847 8848 | */ static void ChannelTimerProc( void *clientData) { Channel *chanPtr = (Channel *)clientData; | < | | | | | | | > > > | | | | > > > > > > > | | > > > > > > > | 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 | */ static void ChannelTimerProc( void *clientData) { Channel *chanPtr = (Channel *)clientData; /* State info for channel */ ChannelState *statePtr = chanPtr->state; /* TclChannelPreserve() must be called before the current function was * scheduled, is already in effect. In this function it guards against * deallocation in Tcl_NotifyChannel and also keps the channel preserved * until ChannelTimerProc is later called again. */ if (chanPtr->typePtr == NULL) { CleanupTimerHandler(statePtr); } else { Tcl_Preserve(statePtr); statePtr->timer = NULL; if (statePtr->interestMask & TCL_WRITABLE && GotFlag(statePtr, CHANNEL_NONBLOCKING) && !GotFlag(statePtr, BG_FLUSH_SCHEDULED) ) { /* * Restart the timer in case a channel handler reenters the event loop * before UpdateInterest gets called by Tcl_NotifyChannel. */ statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_WRITABLE); } else { /* The channel may have just been closed from within Tcl_NotifyChannel */ if (!GotFlag(statePtr, CHANNEL_INCLOSE)) { if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA) && (statePtr->interestMask & TCL_READABLE) && (statePtr->inQueueHead != NULL) && IsBufferReady(statePtr->inQueueHead)) { /* * Restart the timer in case a channel handler reenters the event loop * before UpdateInterest gets called by Tcl_NotifyChannel. */ statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE); } else { CleanupTimerHandler(statePtr); UpdateInterest(chanPtr); } } else { CleanupTimerHandler(statePtr); } } Tcl_Release(statePtr); } } static void DeleteTimerHandler( ChannelState *statePtr ) { if (statePtr->timer != NULL) { Tcl_DeleteTimerHandler(statePtr->timer); CleanupTimerHandler(statePtr); } } static void CleanupTimerHandler( ChannelState *statePtr ){ TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr); statePtr->timer = NULL; statePtr->timerChanPtr = NULL; } /* *---------------------------------------------------------------------- * * Tcl_CreateChannelHandler -- * |
︙ | ︙ |
Changes to generic/tclIO.h.
︙ | ︙ | |||
184 185 186 187 188 189 190 191 192 193 194 195 196 197 | int interestMask; /* Mask of all events this channel has * handlers for. */ EventScriptRecord *scriptRecordPtr; /* Chain of all scripts registered for event * handlers ("fileevent") on this channel. */ Tcl_Size bufSize; /* What size buffers to allocate? */ Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */ struct CopyState *csPtrR; /* State of background copy for which channel * is input, or NULL. */ struct CopyState *csPtrW; /* State of background copy for which channel * is output, or NULL. */ Channel *topChanPtr; /* Refers to topmost channel in a stack. Never * NULL. */ Channel *bottomChanPtr; /* Refers to bottommost channel in a stack. | > > > | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | int interestMask; /* Mask of all events this channel has * handlers for. */ EventScriptRecord *scriptRecordPtr; /* Chain of all scripts registered for event * handlers ("fileevent") on this channel. */ Tcl_Size bufSize; /* What size buffers to allocate? */ Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */ Channel *timerChanPtr; /* Needed in order to decrement the refCount of the right channel when the timer is deleted. */ struct CopyState *csPtrR; /* State of background copy for which channel * is input, or NULL. */ struct CopyState *csPtrW; /* State of background copy for which channel * is output, or NULL. */ Channel *topChanPtr; /* Refers to topmost channel in a stack. Never * NULL. */ Channel *bottomChanPtr; /* Refers to bottommost channel in a stack. |
︙ | ︙ |