Reputation: 7622
Step 1: I open a terminal and type
mkfifo mypipe
cat < mypipe
Step 2: I open another and type:
for elem in {1..100} ; do echo "$elem" > mypipe ; done
A random ammount of numbers get printed, the first script exits and the second hangs. Please share the wizdom. Ubuntu bug? If more info is needed please ask, i don't imagine anything relevant atm.
Thx, you guys are awesome.
Upvotes: 1
Views: 241
Reputation: 111239
The way named pipes work is that when the writing process closes the pipe, the reading process receives an EOF. When cat
sees the file has ended it stops reading and exits. Here bash seems to reuse the open file most of the time in the loop, rather than closing and reopening it in each run.
To ensure that the file is opened and closed exactly once you could write this:
(for elem in {1..100} ; do echo "$elem" ; done) > mypipe
To get cat
output exactly one number in each run you have to use the program /bin/echo
rather than the built-in echo
. This forces Bash to open and close the file in each run of the loop:
for elem in {1..100} ; do /bin/echo "$elem" > mypipe ; done
Upvotes: 1
Reputation: 56059
If there's a bug, it's that the cat
side prints more than one. It's a race condition. What's happening there is that the cat
is reading one line, before it can read the EOF afterwards (because they're separate writes) the echo
writes the next line, so cat
gets that, etc. Eventually, it seems, cat
reaches an EOF before the echo
redirect can write to the pipe. If you want to write all the numbers to the pipe at once, move the redirect to the end:
for elem in {1..100} ; do echo "$elem" done > mypipe
Or better,
seq 100 > mypipe
If you want cat
to get only one at a time... I'm not quite sure how you can do that easily (Though I believe I could hack it if necessary).
Upvotes: 1