diff options
author | pooryorick <com.digitalsmarties@pooryorick.com> | 2023-04-03 17:13:19 (GMT) |
---|---|---|
committer | pooryorick <com.digitalsmarties@pooryorick.com> | 2023-04-03 17:13:19 (GMT) |
commit | 1215212601c8aea0a5f967b35315beee35e565f1 (patch) | |
tree | 3216ca2767f9c9f989c182fa6bdc2394cf5bc399 | |
parent | 5e5a852fe0635c73bda5b6fea1a265373208e4cf (diff) | |
parent | 3e6eaa5776cbff53a13c50cbf5592e65307bd6bb (diff) | |
download | tcl-1215212601c8aea0a5f967b35315beee35e565f1.zip tcl-1215212601c8aea0a5f967b35315beee35e565f1.tar.gz tcl-1215212601c8aea0a5f967b35315beee35e565f1.tar.bz2 |
Fix for [9ca87e6286262a62], sync fcopy buffers input in ReadChars().
-rw-r--r-- | generic/tclIO.c | 12 | ||||
-rw-r--r-- | tests/io.test | 28 |
2 files changed, 34 insertions, 6 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 287a2f2..73d787a 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -196,7 +196,7 @@ static void DiscardOutputQueued(ChannelState *chanPtr); static Tcl_Size DoRead(Channel *chanPtr, char *dst, Tcl_Size bytesToRead, int allowShortReads); static Tcl_Size DoReadChars(Channel *chan, Tcl_Obj *objPtr, Tcl_Size toRead, - int appendFlag); + int allowShortReads, int appendFlag); static int FilterInputBytes(Channel *chanPtr, GetsState *statePtr); static int FlushChannel(Tcl_Interp *interp, Channel *chanPtr, @@ -5899,7 +5899,7 @@ Tcl_ReadChars( return TCL_INDEX_NONE; } - return DoReadChars(chanPtr, objPtr, toRead, appendFlag); + return DoReadChars(chanPtr, objPtr, toRead, 0, appendFlag); } /* *--------------------------------------------------------------------------- @@ -5930,6 +5930,7 @@ DoReadChars( Tcl_Size toRead, /* Maximum number of characters to store, or * TCL_INDEX_NONE to read all available data (up to EOF or * when channel blocks). */ + int allowShortReads, /* Allow half-blocking (pipes,sockets) */ int appendFlag) /* If non-zero, data read from the channel * will be appended to the object. Otherwise, * the data will replace the existing contents @@ -6070,8 +6071,8 @@ DoReadChars( if (GotFlag(statePtr, CHANNEL_EOF)) { break; } - if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_BLOCKED) - == (CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)) { + if ((GotFlag(statePtr, CHANNEL_NONBLOCKING) || allowShortReads) + && GotFlag(statePtr, CHANNEL_BLOCKED)) { break; } result = GetInput(chanPtr); @@ -9762,7 +9763,8 @@ CopyData( !GotFlag(inStatePtr, CHANNEL_NONBLOCKING)); } else { size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb, - 0 /* No append */); + !GotFlag(inStatePtr, CHANNEL_NONBLOCKING) + ,0 /* No append */); } underflow = (size >= 0) && ((size_t)size < sizeb); /* Input underflow */ } diff --git a/tests/io.test b/tests/io.test index 96e5ea6..22b7482 100644 --- a/tests/io.test +++ b/tests/io.test @@ -8276,7 +8276,7 @@ test io-53.11 {Bug 2895565} -setup { removeFile out removeFile in } -result {40 bytes copied} -test io-53.12 {CopyData: foreground short reads, aka bug 3096275} {stdio unix fcopy} { +test io-53.12.0 {CopyData: foreground short reads, aka bug 3096275} {stdio unix fcopy} { file delete $path(pipe) set f1 [open $path(pipe) w] puts -nonewline $f1 { @@ -8295,6 +8295,32 @@ test io-53.12 {CopyData: foreground short reads, aka bug 3096275} {stdio unix fc close $f1 list $::done $ch } {ok A} +test io-53.12.1 { + Issue 9ca87e6286262a62. + CopyData: foreground short reads via ReadChars(). + Related to report 3096275 for ReadBytes(). + + Prior to the fix this test waited forever for read() to return. +} {stdio unix fcopy} { + file delete $path(output) + set f1 [open $path(output) w] + puts -nonewline $f1 { + chan configure stdin -encoding iso8859-1 -translation lf -buffering none + fcopy stdin stdout + } + close $f1 + set f1 [open "|[list [info nameofexecutable] $path(output)]" r+] + try { + chan configure $f1 -encoding utf-6 -buffering none + puts -nonewline $f1 A + set ch [read $f1 1] + } finally { + if {$f1 in [chan names]} { + close $f1 + } + } + lindex $ch +} A test io-53.13 {TclCopyChannel: read error reporting} -setup { proc driver {cmd args} { variable buffer |