Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Backport 8.6's fix [checkin 5af0d249de] to [Bug 2901998]: Inconsistent buffered I/O. Tcl's I/O now flushes buffered output before reading, discards buffered input before writing, etc. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | core-8-5-branch |
Files: | files | file ages | folders |
SHA1: |
e7d7fe409abbf3f165868795d70f8f8c |
User & Date: | ferrieux 2013-05-01 21:13:03 |
Context
2013-05-06
| ||
07:22 | Add support for Cygwin64, which has a 64-bit "long" type. Binary compatibility with win64 requires ... check-in: 95f65c60b8 user: jan.nijtmans tags: core-8-5-branch | |
06:48 | merge-mark check-in: 86970292d9 user: jan.nijtmans tags: trunk | |
2013-05-01
| ||
21:13 | Backport 8.6's fix [checkin 5af0d249de] to [Bug 2901998]: Inconsistent buffered I/O. Tcl's I/O now f... check-in: e7d7fe409a user: ferrieux tags: core-8-5-branch | |
2013-04-30
| ||
18:46 | (::platform::LibcVersion): Followup to the 2013-01-30 change. The RE become too restrictive again. S... check-in: d220e04846 user: andreask tags: core-8-5-branch | |
Changes
Changes to generic/tclIO.c.
︙ | ︙ | |||
225 226 227 228 229 230 231 232 233 234 235 236 237 238 | static int WriteBytes(Channel *chanPtr, const char *src, int srcLen); static int WriteChars(Channel *chanPtr, const char *src, int srcLen); static Tcl_Obj * FixLevelCode(Tcl_Obj *msg); static void SpliceChannel(Tcl_Channel chan); static void CutChannel(Tcl_Channel chan); /* * Simplifying helper macros. All may use their argument(s) multiple times. * The ANSI C "prototypes" for the macros are listed below, together with a * short description of what the macro does. * * -------------------------------------------------------------------------- | > | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | static int WriteBytes(Channel *chanPtr, const char *src, int srcLen); static int WriteChars(Channel *chanPtr, const char *src, int srcLen); static Tcl_Obj * FixLevelCode(Tcl_Obj *msg); static void SpliceChannel(Tcl_Channel chan); static void CutChannel(Tcl_Channel chan); static int WillRead(Channel *chanPtr); /* * Simplifying helper macros. All may use their argument(s) multiple times. * The ANSI C "prototypes" for the macros are listed below, together with a * short description of what the macro does. * * -------------------------------------------------------------------------- |
︙ | ︙ | |||
338 339 340 341 342 343 344 345 346 347 348 349 350 351 | ((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (storePtr)) #define BUSY_STATE(st,fl) \ ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \ (((st)->csPtrW) && ((fl) & TCL_WRITABLE))) #define MAX_CHANNEL_BUFFER_SIZE (1024*1024) /* *--------------------------------------------------------------------------- * * TclInitIOSubsystem -- * * Initialize all resources used by this subsystem on a per-process | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 | ((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (storePtr)) #define BUSY_STATE(st,fl) \ ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \ (((st)->csPtrW) && ((fl) & TCL_WRITABLE))) #define MAX_CHANNEL_BUFFER_SIZE (1024*1024) /* * ChanRead, dropped here by a time traveler, see 8.6 */ static inline int ChanRead( Channel *chanPtr, char *dst, int dstSize, int *errnoPtr) { if (WillRead(chanPtr) < 0) { return -1; } return chanPtr->typePtr->inputProc(chanPtr->instanceData, dst, dstSize, errnoPtr); } static inline Tcl_WideInt ChanSeek( Channel *chanPtr, Tcl_WideInt offset, int mode, int *errnoPtr) { /* * Note that we prefer the wideSeekProc if that field is available in the * type and non-NULL. */ if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) && chanPtr->typePtr->wideSeekProc != NULL) { return chanPtr->typePtr->wideSeekProc(chanPtr->instanceData, offset, mode, errnoPtr); } if (offset<Tcl_LongAsWide(LONG_MIN) || offset>Tcl_LongAsWide(LONG_MAX)) { *errnoPtr = EOVERFLOW; return Tcl_LongAsWide(-1); } return Tcl_LongAsWide(chanPtr->typePtr->seekProc(chanPtr->instanceData, Tcl_WideAsLong(offset), mode, errnoPtr)); } /* *--------------------------------------------------------------------------- * * TclInitIOSubsystem -- * * Initialize all resources used by this subsystem on a per-process |
︙ | ︙ | |||
3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 | src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen); return WriteBytes(chanPtr, src, srcLen); } else { src = TclGetStringFromObj(objPtr, &srcLen); return WriteChars(chanPtr, src, srcLen); } } /* *---------------------------------------------------------------------- * * WriteBytes -- * * Write a sequence of bytes into an output buffer, may queue the buffer | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 | src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen); return WriteBytes(chanPtr, src, srcLen); } else { src = TclGetStringFromObj(objPtr, &srcLen); return WriteChars(chanPtr, src, srcLen); } } static void WillWrite(Channel *chanPtr) { int inputBuffered; if ((chanPtr->typePtr->seekProc != NULL) && ((inputBuffered = Tcl_InputBuffered((Tcl_Channel) chanPtr)) > 0)) { int ignore; DiscardInputQueued(chanPtr->state, 0); ChanSeek(chanPtr, - inputBuffered, SEEK_CUR, &ignore); } } static int WillRead(Channel *chanPtr) { if ((chanPtr->typePtr->seekProc != NULL) && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) { if ((chanPtr->state->curOutPtr != NULL) && IsBufferReady(chanPtr->state->curOutPtr)) { SetFlag(chanPtr->state, BUFFER_READY); } if (FlushChannel(NULL, chanPtr, 0) != 0) { return -1; } } return 0; } /* *---------------------------------------------------------------------- * * WriteBytes -- * * Write a sequence of bytes into an output buffer, may queue the buffer |
︙ | ︙ | |||
3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 | int srcLen) /* Number of bytes to write. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; char *dst; int dstMax, sawLF, savedLF, total, dstLen, toWrite, translate; total = 0; sawLF = 0; savedLF = 0; translate = (statePtr->flags & CHANNEL_LINEBUFFERED) || (statePtr->outputTranslation != TCL_TRANSLATE_LF); | > > > > | 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 | int srcLen) /* Number of bytes to write. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; char *dst; int dstMax, sawLF, savedLF, total, dstLen, toWrite, translate; if (srcLen) { WillWrite(chanPtr); } total = 0; sawLF = 0; savedLF = 0; translate = (statePtr->flags & CHANNEL_LINEBUFFERED) || (statePtr->outputTranslation != TCL_TRANSLATE_LF); |
︙ | ︙ | |||
3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 | ChannelBuffer *bufPtr; char *dst, *stage; int saved, savedLF, sawLF, total, dstLen, stageMax, dstWrote; int stageLen, toWrite, stageRead, endEncoding, result; int consumedSomething, translate; Tcl_Encoding encoding; char safe[BUFFER_PADDING]; total = 0; sawLF = 0; savedLF = 0; saved = 0; encoding = statePtr->encoding; | > > > > | 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 | ChannelBuffer *bufPtr; char *dst, *stage; int saved, savedLF, sawLF, total, dstLen, stageMax, dstWrote; int stageLen, toWrite, stageRead, endEncoding, result; int consumedSomething, translate; Tcl_Encoding encoding; char safe[BUFFER_PADDING]; if (srcLen) { WillWrite(chanPtr); } total = 0; sawLF = 0; savedLF = 0; saved = 0; encoding = statePtr->encoding; |
︙ | ︙ | |||
5183 5184 5185 5186 5187 5188 5189 | * the remaining request. Do all the error handling by * ourselves. The code was stolen from 'GetInput' and slightly * adapted (different return value here). * * The case of 'bytesToRead == 0' at this point cannot happen. */ | | | | 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 | * the remaining request. Do all the error handling by * ourselves. The code was stolen from 'GetInput' and slightly * adapted (different return value here). * * The case of 'bytesToRead == 0' at this point cannot happen. */ nread = ChanRead(chanPtr, bufPtr + copied, bytesToRead - copied, &result); #ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING } #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ if (nread > 0) { /* |
︙ | ︙ | |||
6349 6350 6351 6352 6353 6354 6355 | */ nread = -1; result = EWOULDBLOCK; } else { #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ | < | | 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 | */ nread = -1; result = EWOULDBLOCK; } else { #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ nread = ChanRead(chanPtr, InsertPoint(bufPtr), toRead, &result); #ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING } #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ if (nread > 0) { bufPtr->nextAdded += nread; |
︙ | ︙ | |||
6653 6654 6655 6656 6657 6658 6659 | * is buffered, cannot compute the current position. */ inputBuffered = Tcl_InputBuffered(chan); outputBuffered = Tcl_OutputBuffered(chan); if ((inputBuffered != 0) && (outputBuffered != 0)) { | | | > | 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 | * is buffered, cannot compute the current position. */ inputBuffered = Tcl_InputBuffered(chan); outputBuffered = Tcl_OutputBuffered(chan); if ((inputBuffered != 0) && (outputBuffered != 0)) { //Tcl_SetErrno(EFAULT); //return Tcl_LongAsWide(-1); } /* * Get the current position in the device and compute the position where * the next character will be read or written. Note that we prefer the * wideSeekProc if that is available and non-NULL... */ if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) && chanPtr->typePtr->wideSeekProc != NULL) { curPos = (chanPtr->typePtr->wideSeekProc) (chanPtr->instanceData, Tcl_LongAsWide(0), SEEK_CUR, &result); } else { curPos = Tcl_LongAsWide((chanPtr->typePtr->seekProc) ( chanPtr->instanceData, 0, SEEK_CUR, &result)); } if (curPos == Tcl_LongAsWide(-1)) { Tcl_SetErrno(result); return Tcl_LongAsWide(-1); } if (inputBuffered != 0) { return curPos - inputBuffered; } return curPos + outputBuffered; } /* |
︙ | ︙ | |||
6776 6777 6778 6779 6780 6781 6782 | } /* * Seek first to force a total flush of all pending buffers and ditch any * pre-read input data. */ | > | > | | 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 | } /* * Seek first to force a total flush of all pending buffers and ditch any * pre-read input data. */ WillWrite(chanPtr); if (WillRead(chanPtr) < 0) { return TCL_ERROR; } /* * We're all flushed to disk now and we also don't have any unfortunate * input baggage around either; can truncate with impunity. */ |
︙ | ︙ |