bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: read command sometimes misses newline on timeout


From: Martin D Kealey
Subject: Re: read command sometimes misses newline on timeout
Date: Sun, 6 Oct 2024 16:31:56 +1000

The read builtin could return an exit status of (128|SIGALRM) in two
circumstances:

1. If a signal is caught during the read syscall, then either the read
system call returns -1 with EINTR and the error is reported. (Otherwise it
must return a positive byte count, causing the built-in continues until it
gets a delimiter.)

2. If a signal is caught between read syscalls, it could (by a variety of
mechanisms) replace the exit status of the read built-in with a non zero
number. Presumably this is what you're seeing in fuzzing?

I will take a look at builtins/read.def when I get home. I suspect it's
looking at the "have I received SIGALRM" flag before looking at the "have I
read a delimiter" flag; I will report back on what I find.

On Fri, 4 Oct 2024, 22:18 Thomas Oettli via Bug reports for the GNU Bourne
Again SHell, <bug-bash@gnu.org> wrote:

> Configuration Information [Automatically generated, do not change]:
> Machine: x86_64
> OS: linux-gnu
> Compiler: x86_64-pc-linux-gnu-gcc
> Compilation CFLAGS: -O2 -pipe
> uname output: Linux testserver 6.6.47-gentoo #1 SMP Tue Aug 20 09:38:16
> CEST 2024 x86_64 Intel(R) Xeon(R) Gold 6242 CPU @ 2.80GHz GenuineIntel
> GNU/Linux
> Machine Type: x86_64-pc-linux-gnu
>
> Bash Version: 5.2
> Patch Level: 26
> Release Status: release
>
> Description:
>         I have tried to write a bash script that asynchronously reads from
> a pipe (line by line) with the help of "read -t".
>     If the timeout occurs in just the right moment, read returns the full
> line, but the return code says timeout (rc > 128).
>     Therefor it is not possible to know if a full line was returned or
> not. Please see the script in the Repeat-By section that reproduces the
> error in seconds.
>
>
> Repeat-By:
>     function reader() {
>       local buf line
>       while :; do
>         read -t .01 buf
>         rc=$?
>         if (( rc == 0 )); then
>           line+=$buf
>         elif (( rc > 128 )); then
>           line+=$buf
>           continue
>         fi
>         [[ $line != TEST ]] && echo Invalid line: $line && exit
>         echo OK
>         line=""
>       done
>     }
>     reader < <(
>       while :; do
>         echo -n TEST
>         sleep .00$(($RANDOM%10))
>         echo
>       done
>     )
>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]