views:

2688

answers:

3

I'm looking to call a subprocess with a file descriptor opened to a given pipe such that the open() call does not hang waiting for the other side of the pipe to receive a connection.

To demonstrate:

$ mkfifo /tmp/foobar.pipe
$ some_program --command-fd=5 5</tmp/foobar.pipe

In this case, some_program is not run until some process has /tmp/foobar.pipe open for write; however, some_program has useful effects even when it isn't receiving commands, so desired behavior is for some_program to be immediately executed.

Mechanisms to do this by exec'ing through an alternate scripting language (python, perl, etc) or a C wrapper which open /tmp/foobar.pipe with the O_NONBLOCK flag are obvious; I'm looking for a pure-bash solution, should one be possible.

+2  A: 

The only way I know getting this kind of result is a hack:

mkfifo /tmp/foobar.in
mkfifo /tmp/foobar.out
( cat </tmp/foobar.in ) >/tmp/foobar.out &
some_program --command-fd=5 5</tmp/foobar.out

perhaps this helps :-)

Sec
you're right it was a typo. just edited it. And yes the background process is ugly, this is why I called it a hack :)
Sec
+2  A: 

Opening the FD read/write rather than read-only when setting up the pipeline prevents blocking.

To be a bit more specific:

$ mkfifo /tmp/foobar.pipe
$ some_program --command-fd=5 5<>/tmp/foobar.pipe

prevents the undesired blocking behavior, as 5<>/tmp/foobar.pipe opens in RW mode (as opposed to opening in read-only mode as with 5</tmp/foobar.pipe) although O_NONBLOCK is still set. Thanks to waldner on irc://irc.freenode.org/#bash for this pointer.

Charles Duffy
A: 

What language is some_program written in? Unless it is written in shell itself, or is not intended to be aware that it is sometimes connected to a FIFO, then the program should probably deal with the issue. In C or Perl (and probably Python and the rest), you can gain enough control over the open not to block when you open a FIFO.

In general, programs that need to interact accurately with a FIFO need to be aware that they are dealing with a FIFO, especially if they need to interact without blocking unexpectedly,

Jonathan Leffler
The program *can't* "deal with the issue" (or do anything else) until after it has been invoked. The shell calls open(), which is blocking, while setting up the pipeline, so some_program has not yet been started.
Charles Duffy
To expand on why this is being done by the caller -- there are privilege issues going on here; some_program is actually run in a very restrictive jail, and is unable to set up the fifo itself.
Charles Duffy