Why does Bash read -t still block when the FIFO writer exits?

0
0
Asked By MellowPine47 On

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

Answered By CopperLark82 On

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.

QuietMaple19 -

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

Answered By AmberCactus31 On

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.

Answered By SilverOtter6 On

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.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.