I'm using Bash 5.2.37 with a named pipe. The reader repeatedly runs `read -t 1 `, checks the exit status, and expects a timeout after one second. A separate writer sends `$RANDOM` to the FIFO every half-second. This works while the writer is running, but after the writer exits, the reader blocks indefinitely instead of timing out. Why doesn't `read` honor the timeout, and what is the correct way to structure these scripts?
3 Answers
The timeout applies to Bash’s `read` operation, but your redirection opens the FIFO first. Every time this runs, `read -t 1 <the_fifo` opens the named pipe anew. Opening a FIFO for reading blocks until some process opens it for writing, so Bash never gets as far as starting `read` or applying its timeout.
One option is to open the FIFO in read-write mode so the open succeeds immediately:
```bash
while true; do
read -t 1 the_fifo
ec=$?
echo "EC $ec"
# handle the result here
done
```
A cleaner design is usually to open the FIFO once, outside the loop, rather than reopening it for every line. Using `` can also be useful for the writer if it should open successfully before a reader exists, although writes can still block once the pipe buffer fills.
The writer should normally keep the FIFO open for the whole loop rather than perform a fresh `>the_fifo` redirection on every iteration. Repeated redirections repeatedly open and close the pipe, which makes the reader’s behavior harder to reason about. Put the redirection on the loop, and add cleanup for the FIFO when the script exits if the temporary named pipe should be removed.
The FIFO can be handled directly as the condition of the loop, for example:
```bash
while IFS= read -r line; do
echo "value=$line"
done the_fifo
```
If a line is not terminated with a newline, a timed `read` can instead return a timeout status after waiting for the rest of that line. With normal newline-terminated output, EOF and the pipe’s open/close behavior are the main issues here.

You can also put the redirection on the loop itself. That way the FIFO is opened once, and when the other process closes its end, the loop can terminate instead of repeatedly waiting for a new writer:
```bash
while read -t 1; do
echo "value=$REPLY"
done