bash blocking on exec assigning an output file descriptor to a fifo

2012-02-14 Thread Øyvind Hvidsten
Please correct any mistakes in my wording, as I would very much like to 
be able to use the correct terms when describing this. Also, please ask 
if anything is unclear :)


My problem occurs when I do the following:
mkfifo foo; exec 3<"foo"; echo done

This blocks on the exec statement, and never reaches the echo statement, 
even though I don't think I've asked bash to read from that file 
descriptor (yet). The plan was to use "read -t 0 <&3" at a later stage 
to check if something is available there.


The following series of statements will however not block and echo 
"done" immediately:

mkfifo foo; exec 3<>"foo"; echo done

This also blocks:
mkfifo foo; exec 3>"foo"; exec 3<"foo"; echo done

Why is this?

My current version of bash:
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)



Re: bash blocking on exec assigning an output file descriptor to a fifo

2012-02-14 Thread Chet Ramey
On 2/14/12 4:04 PM, Øyvind Hvidsten wrote:
> Please correct any mistakes in my wording, as I would very much like to be
> able to use the correct terms when describing this. Also, please ask if
> anything is unclear :)
> 
> My problem occurs when I do the following:
> mkfifo foo; exec 3<"foo"; echo done
> 
> This blocks on the exec statement, and never reaches the echo statement,
> even though I don't think I've asked bash to read from that file descriptor
> (yet). The plan was to use "read -t 0 <&3" at a later stage to check if
> something is available there.

This is from the Posix description of `open'.  Bash uses O_WRONLY and
O_RDONLY when opening files for output or input, respectively (> and <).
It does not use O_NONBLOCK.

==
When opening a FIFO with O_RDONLY or O_WRONLY set:

If O_NONBLOCK is set, an open() for reading-only shall return without
delay. An open() for writing-only shall return an error if no process
currently has the file open for reading.

If O_NONBLOCK is clear, an open() for reading-only shall block the
calling thread until a thread opens the file for writing. An open() for
writing-only shall block the calling thread until a thread opens the file
for reading.
==

exec 3<>foo works because it uses O_RDWR.  This is just how FIFOs work.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: bash blocking on exec assigning an output file descriptor to a fifo

2012-02-14 Thread Eric Blake
On 02/14/2012 02:04 PM, Øyvind Hvidsten wrote:
> Please correct any mistakes in my wording, as I would very much like to
> be able to use the correct terms when describing this. Also, please ask
> if anything is unclear :)
> 
> My problem occurs when I do the following:
> mkfifo foo; exec 3<"foo"; echo done
> 
> This blocks on the exec statement, and never reaches the echo statement,

Correct.

> even though I don't think I've asked bash to read from that file
> descriptor (yet).

But POSIX says that it is not just reads from a fifo that block, but
open() itself will block.  And you _did_ ask bash to open(O_RDONLY) the
fifo into fd 3, which means it will block until there is a writer.

> The plan was to use "read -t 0 <&3" at a later stage
> to check if something is available there.

Then don't open it for reading until that later point:

read -t 0  
> The following series of statements will however not block and echo
> "done" immediately:
> mkfifo foo; exec 3<>"foo"; echo done

This is inherently non-portable - it says to open "foo" with O_RDWR
privileges, which POSIX says does not have to work (and on cygwin, it
does not work).  But on Linux, where it does work, it doesn't block,
since you are opening a writer at the same time as the reader, so you've
gotten past the open() block and can now rely on the read() and write()
blocking.

> 
> This also blocks:
> mkfifo foo; exec 3>"foo"; exec 3<"foo"; echo done

Yep.

> 
> Why is this?

Opening a fifo for writing without a reader also blocks, also per POSIX.

If you want a single shell script to portably handle both reading and
writing into the same fifo, then you have to use a subshell and
backgrounding in order to split the shell script into two processes, one
reading and one writing, and recognize that whichever of the parent or
subshell uses the fifo first will block until the counterpart process
opens the same fifo in the other direction.

-- 
Eric Blake   ebl...@redhat.com+1-919-301-3266
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


Re: bash blocking on exec assigning an output file descriptor to a fifo

2012-02-14 Thread Dan Douglas
O_NONBLOCK is up there in things I wouldn't mind using. Namely, having access 
to errno. I don't see any way of determining the "fullness" of a buffer even 
through /proc/self/fdinfo/ on Linux.
-- 
Dan Douglas

signature.asc
Description: This is a digitally signed message part.