Balaji Reddy
Balaji Reddy

Reputation: 475

How to flush named pipe(FIFO) in non-blocking mode in busybox shell script?

I tried using "cat" and "dd" commands to flush the FIFO and both commands blocks the operation.

Below are the commands used to flush,

Create FIFO

mkfifo tmp.fifo

Using "cat" command

cat tmp.fifo 

OR even using file descriptor with cat command like,

exec 200<> tmp/fifo; 
cat <&200 > /dev/null

Using "dd" command

dd if=tmp.fifo of=/dev/null

Note:

"dd" command works well (doesn't block) in Linux PC terminal with the help of 'iflag' like,

dd if=tmp/fifo iflag=nonblock of=/dev/null

(!) But this doesn't work with busybox's version of dd. How can I achieve it using busybox?

Upvotes: 4

Views: 4684

Answers (2)

TrinitronX
TrinitronX

Reputation: 5223

The answer depends on the meaning of flush in the question.

If flush is meant in the sense of:

  • "clearing the buffer": Then the answer above should suffice. It will read all data from the pipe, outputting to /dev/null.
    • Alternatively, you can write to the pipe using /dev/null as input which should send an EOF condition to the program reading from the pipe. (Note that if there is no reader, then writes will block).
  • "flushing data quickly" (e.g. for line or unbuffered IO to/from named pipes & FIFOs): Then you should evaluate whether the stdbuf command (originally from GNU coreutils) will do what you need.

Finally, it may be helpful to review the following resources about PIPE buffering in Linux (as the details of this topic can be rather esoteric):

Upvotes: 0

Charles Duffy
Charles Duffy

Reputation: 295500

It's easy to check whether/how this is possible, just by looking at the busybox source: No references to O_NONBLOCK exist anywhere in the busybox codebase.

Thus: With busybox alone, this is not possible.


Now, what you can do (if your kernel's behavior is appropriate -- POSIX doesn't specify behavior of named pipes in this mode, leaving it implementation-defined) is open the pipeline with O_RW (so it doesn't need a writer) and perform a blocking read, with another process killing this after a timeout:

exec 5<>yourpipe
cat <&5 >/dev/null & cat_pid=$!
sleep 1
kill "$cat_pid"

It's an ugly, inefficient, and questionably portable hack -- but without adding extra dependencies (Python, Perl, a tiny C helper), it's what you've got.

Upvotes: 4

Related Questions