Mail Archives: cygwin/2007/05/08/12:11:03
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/
- Raw text -