Configuration Information [Automatically generated, do not change]: Machine: i386 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='i386' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i386-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I../bash -I../bash/include -I../bash/lib -g -O2 uname output: Linux bugs 2.6.10-5-k7 #1 Tue Apr 5 12:56:05 UTC 2005 i686 GNU/Linux Machine Type: i386-pc-linux-gnu
Bash Version: 3.0 Patch Level: 16 Release Status: release Description: If "read -t" times out without fulfilling a request, any pending data is lost. Via strace it's apparent that the problem is that when the user requests a line of data, bash read is actually calling read() with a buffer size of one. So bash is holding the data. It's not in the OS file buffer. Then when the timeout occurs, bash does not return the read data to the user, or associate it with the file descriptor. This happens when doing any multi-character read (line, delimeter, or -n greater than one). The only work-around is -n 1, which is painfully slow. Repeat-By: This is easiest to see when reading from a pipe. The "coproc.bash" example code in the distribution shows it quite easily. Spawn a telnet coprocess, and do a read loop something like while coprocess read -t 1 line; do echo "received (${line})" done Now, if you write commands to the coprocess, then invoke the read loop, you'll find that the command prompts from the telnet session are sometimes lost. This is because there's no carriage return after the prompt. Then read times out, and bash throws away the data that was read. You can also do it with something like the following function readloop() { while read -t 1 line <&62; do echo "line (${line})" done } fifo=/var/tmp/cot rm -f $fifo mkfifo $fifo { echo -en "This is a\ncomplete"; sleep 4; echo " sentence."; } >$fifo & exec 62<$fifo readloop readloop readloop readloop readloop Fix: The read function should either store the read data with the file descriptor, and prepend it to any later data read from the same file descriptor, or it should return the read data to the user when the read times out. If the data is stored there could be complications with duped file descriptors. I dunno about that. Returning the data to the user seems like the less error-prone thing to do, though in that case it's important that the "name" parameters all be set to null if no data is read. Otherwise it is ambiguous on timeout whether the same string was read, or no data was read. Returning the data to the user also seems the most flexible for the programmer, since the programmer can then decide whether to prepend the data to the next buffer, or take advantage of having all of the available data from the file descriptor w/o needing to use -n 1 (one character read loops in shell script really should be avoided). _______________________________________________ Bug-bash mailing list Bug-bash@gnu.org http://lists.gnu.org/mailman/listinfo/bug-bash