Tcl Source Code

View Ticket
Login
Ticket UUID: 3096275
Title: Sync fcopy buffers input
Type: Bug Version: None
Submitter: ferrieux Created on: 2010-10-27 08:32:25
Subsystem: 25. Channel System Assigned To: dgp
Priority: 9 Immediate Severity: Minor
Status: Closed Last Modified: 2023-04-03 18:16:19
Resolution: Fixed Closed By: pooryorick
    Closed on: 2023-04-03 18:16:19
Description:
The following script:

 fconfigure stdin -translation binary -blocking 0
 fconfigure stdout -buffering none -translation binary
 fcopy stdin stdout

when fed by typing lines to stdin, will not output anything until either 4k have been typed or eof, despite the nonblocking mode on stdin.
The same using an async fcopy, will work in a more responsive manner:

 fcopy stdin stdout -command done
 vwait forever

This is a consequence of the following credo, in a comment in TclCopyChannel:

    /*
     * Set up the blocking mode appropriately. Background copies need
     * non-blocking channels. Foreground copies need blocking channels. If
     * there is an error, restore the old blocking mode.
     */

As a consequence, while GetInput happily returns short reads, DoRead insists on filling up its 4k buffer.

That is, sync fcopy will never pass short reads on to the output channel. Hence, sync fcopy is not adapted to live streams, while async fcopy is.

This it at least surprising for the developer, since the sync/async fcopy decision is rather based on external considerations like "do I need to interleave it with other IO" or "do I need to keep a GUI responsive". The fact that chosing sync implies buffering by 4k is nowhere in the docs.

Low prio because it's a Day-1 issue :/
User Comments: pooryorick added on 2023-04-03 18:16:19:

This report dealt with ReadBytes(). See also [9ca87e6286] for the same issue with ReadChars().


ferrieux added on 2011-08-19 03:24:24:
Committed.

ferrieux added on 2011-07-19 22:42:07:
Any hope to review for 8.6.0 ?

ferrieux added on 2010-11-05 04:45:05:
Also ran tclbench: no slowdown.

ferrieux added on 2010-10-28 03:40:32:
That can no more occur than before: the new behavior, allowShortReads, is only ever activated when 

                              !GotFlag(inStatePtr, CHANNEL_NONBLOCKING)

that is, only for a blocking channel, ie in sync fcopy.
If you know of another situation yielding a busyloop, please elaborate.

andreas_kupries added on 2010-10-28 02:33:32:
I can't see anything bad with this, except, maybe, that the sync fcopy go into a tight loop consuming lots of cpu because of a  continuous series of 0-char reads until  something is typed in.

Would like to get a second opinion, assigning to Jeff.

ferrieux added on 2010-10-27 17:13:16:

File Added - 391352: fcopysync.patch

ferrieux added on 2010-10-27 17:12:32:
Attached tiny patch fixes the issue, by adding an allowShortReads flag to DoRead, for use only inside CopyData when the input channel is blocking. This allows to exploit the "half-blocking" semantics of pipes and sockets, which can do short reads in blocking mode, thus keeping the overall spirit of sync fcopy (ie don't use the event loop).

Checked against the test suite.
Again, this removes a day-1, but undocumented, limitation.
Raising prio to ask for permission to commit.

Attachments: