5

I have a trivial Python script:

#!/usr/bin/python

import os, sys

sys.stderr.write('I am %s' % os.getpid())
sys.stderr.flush()

print "hello"

sys.stderr.write('I am done')

When I run this script from Bash and redirect the stdout to FIFO:

$ mkfifo fifo
$ /pyscript > fifo

the strange thing is, that before I read from the FIFO:

  • I won't get the "I am (PID)" message,

  • I can't see the script using ps -ef

  • and using lsof, I can't see anybody has the fifo file open!

Once I do read from the FIFO, the both messages that I'm writing to stderr appear at once.

What is happening?


The background: I'm writing a test where I create FIFO and write 'hello' to it; then I run a test and expect the SUT to not read from it; ie. just ignore the file. I tried to do mkfifo test_fifo; /bin/echo hello > test_fifo &; run_the_test; killall echo but to my surprise, the echo process never exists! How should I "clean up" after such test (apart from rm test_fifo)...?

5

The shell will not run a program until any file redirections have been completed successfully. The command pyscript > fifo will cause the shell to fork and then try to open fifo. This will succeed only when some process has opened fifo for reading. Until then, the child shell will be in pipe wait.

$ (sleep 10;ps -l -t pts/0)&
[1] 2574
$ pyscript > fifo
F S   UID    PID   PPID WCHAN  TTY    CMD
0 S  1000   2554   2535 wait   pts/0  bash  //interactive shell
1 S  1000   2574   2554 wait   pts/0  bash  //fork of shell, parent of sleep and ps
1 S  1000   2576   2554 pipe_w pts/0  bash  //fork of shell, waiting to open fifo
0 R  1000   2577   2574 -      pts/0  ps
4

A pipe or FIFO has to be open at both ends simultaneously. If you read from a pipe or FIFO file that doesn’t have any processes writing to it (perhaps because they have all closed the file, or exited), the read returns end-of-file. Writing to a pipe or FIFO that doesn’t have a reading process is treated as an error condition; it generates a SIGPIPE signal, and fails with error code EPIPE if the signal is handled or blocked.

http://www.gnu.org/software/libc/manual/html_node/Pipes-and-FIFOs.html

  • Nice, I did not know that FIFO must be open simultaneously; so certainly there must be some magic that the shell does to make it work in the first place...? – Alois Mahdal Oct 26 '15 at 13:31
  • Not really magic; the order of events is 1) The shell makes a system call to open the target file for writing. 2) The shell blocks until that system call returns. 3) The shell runs the command. With a regular file, there is no discernible gap between 1 and 2; it happens almost immediately. With a FIFO, the system call doesn't return until another process opens the FIFO for reading, which can delay 2 indefinitely. – chepner Nov 20 '15 at 14:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.