Buffer size problem with FIFOs [TEST Program Included]

Justin T. Gibbs gibbs@scsiguy.com
Tue May 8 16:40:00 GMT 2007


I have an application (Berkeley make) that manages parallelism using a FIFO.
The FIFO acts as a pool for "work tokens".  All processes,  including 
the first that
opens and "primes" the FIFO, must obtain a token from the FIFO before 
performing
a job and return that token when the job is complete.  Priming the FIFO 
entails writing
N (number of concurrent jobs) 1 byte tokens into the FIFO.  The only 
problem with
this scheme is that it relies on the system having a PIPE_BUF value >= N,
and FIFOs that honor this value.  Otherwise the tokens aren't guaranteed
to fit in the FIFO.

In playing with this in cygwin, I quickly discovered that the named 
pipes used to
implement FIFOs are created with a size of 1 byte.  This is far less 
than cygwin's
PIPE_BUF (4096) or the POSIX mandated minimum for PIPE_BUF (512).
After reviewing the code, the setting seems deliberate  
(fhandler_pipe::create_selectable()
has an explicit check to avoid bumping the size up to PIPE_BUF for 
FIFOs), but I couldn't
find any code comments or changelog entries to explain the restriction.  
Can anyone explain
the requirement for this limit?  My limited testing (large parallel 
builds) after recompiling the
cygwin DLL from CVS with the value bumped up to 512, has shown no ill 
effects.

Here is a simple program that shows the problem.  It runs correctly on 
the "unix" platforms
I have access to (FreeBSD, Linux), but hangs with an unmodified Cygwin.  
Note that the
behavior does not change if I use separate fds for reads and writes 
(O_RDWR is not
guaranteed to work in POSIX - however cygwin does support it and it 
makes the sample
program simpler).

Thanks,
Justin

#include <stdio.h>
#include <fcntl.h>

int
main(int argc, const char **argv)
{
    const char fifoName[] = "/tmp/test_fifo";

    /**
     * Create a FIFO to store our tokens.
     */
    if (mkfifo(fifoName, 0600) == 0) {
        int fd;

        if ((fd = open(fifoName, O_RDWR | O_BINARY, 0600)) >= 0) {

            /** Access the FIFO in nonblocking mode. */
            fcntl(fd, F_SETFL, O_NONBLOCK);

            /* Fill FIFO with two tokens.  This hangs on Cygwin. */
            if (write(fd, "++", 2) == -1)
                warn("Unable to write tokens");
            else {
                int  count;
                char token;

                count = 0;
                while (1) {
                    if (read(fd, &token, 1) == -1)
                        break;
                    count++;
                }
                printf("Read %d tokens\n", count);
            }
        }
        unlink(fifoName);
    }
    return (0);
}


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/



More information about the Cygwin mailing list