bug-bash
[Top][All Lists]
Advanced

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

Re: Reading from a file by using its FD returns its contents only once


From: Chet Ramey
Subject: Re: Reading from a file by using its FD returns its contents only once
Date: Mon, 31 Dec 2018 14:21:30 -0500
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:60.0) Gecko/20100101 Thunderbird/60.3.3

On 12/30/18 8:36 PM, mike b wrote:

> Bash Version: 4.4
> Patch Level: 12
> Release Status: release
> 
> I am not quite sure if this is a bug, but here's what I find as a bit odd
> behavior:

It's not odd.

> # modprobe zram num_devices=0
> # exec {add}</sys/class/zram-control/hot_add
> # read -r id <&"$add"; echo "$id"
> 0
> # read -r id <&"$add"; echo "$id" # <- $id ends up empty, no data is read
> 
> # read -r id </sys/class/zram-control/hot_add; echo "$id"
> 1
> # read -r id </sys/class/zram-control/hot_add; echo "$id"
> 2
> # readlink -f "/proc/$$/fd/$add"
> /sys/class/zram-control/hot_add
> 
> The above sysfs interface is used for creating a zram device by performing
> a read on the hot_add file. The value that should be returned is the id of
> the newly created device. In first instance file is opened by dynamically
> allocating the fd to use "$add" (the fd) across reads instead of
> referencing the file directly. But from the above example you can see that
> $id is assigned an actual value only on first read. On every next one, $id
> would become empty - when using $add, that is. However, when file is read
> in a standard way, by using it directly, everything works as it should.

The difference between the two methods is that the fd method keeps an fd
($add) open to the file and does not rewind it between reads. If the file
returns EOF on the second and subsequent reads from the open file, you'll
get the behavior you observe. The `standard' way opens the file, which has
the side effect of setting the file pointer to 0, each time. I assume the
special file has some sort of behavior triggered by `open', and that's how
the designers intended it to be used.


> The above is just an example. Doing reads on any other regular file like
> this yields same behavior:
> # echo bla >./t
> # exec 10<./t
> # read -r <&10
> # echo $REPLY
> bla
> # read -r <&10
> # echo $REPLY

You're reading to EOF on the first read and getting EOF on the second (this
is basically how `while read' loops work).

> 
> #
> Playing with something like:
> # zram=/sys/class/zram/control/hot_add
> # c=0; while  ((++c <= 3)); do read -r; echo "${REPLY:-NULL}"; done <"$zram"
> 0
> NULL
> NULL

Same.

> #
> also gets same results. In contrast to:
> # c=0; while (( ++c <= 3 )); do read -r; echo "out: ${REPLY:-NULL}"; done
> foo
> out: foo
> foo
> out: foo
> foo
> out: foo
> #
> which keeps reading from default stdin (terminal in this case) without any
> hiccups (as expected).

The terminal doesn't really have an EOF.


-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet@case.edu    http://tiswww.cwru.edu/~chet/



reply via email to

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