This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Buffer size problem with FIFOs [TEST Program Included]


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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]