summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpooryorick <com.digitalsmarties@pooryorick.com>2023-04-03 17:13:19 (GMT)
committerpooryorick <com.digitalsmarties@pooryorick.com>2023-04-03 17:13:19 (GMT)
commit1215212601c8aea0a5f967b35315beee35e565f1 (patch)
tree3216ca2767f9c9f989c182fa6bdc2394cf5bc399
parent5e5a852fe0635c73bda5b6fea1a265373208e4cf (diff)
parent3e6eaa5776cbff53a13c50cbf5592e65307bd6bb (diff)
downloadtcl-1215212601c8aea0a5f967b35315beee35e565f1.zip
tcl-1215212601c8aea0a5f967b35315beee35e565f1.tar.gz
tcl-1215212601c8aea0a5f967b35315beee35e565f1.tar.bz2
Fix for [9ca87e6286262a62], sync fcopy buffers input in ReadChars().
-rw-r--r--generic/tclIO.c12
-rw-r--r--tests/io.test28
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