how to determine if pipe can be written
linux, named-pipes, perl, posix
Solution
Chances are that you are not paying attention to the return codes from `open`. If you open a FIFO for writing and as non-blocking there are two possible outcomes.
If there is already a reader the `open` will immediately return successfully.
If there is no pipe reader the `open` will fail with errno = ENXIO.
The following program demonstrates.
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<stdlib.h>
#include <sys/stat.h>
#define SERVFIFO "/tmp/server.fifo"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
void syserr(const char *str)
{
perror(str);
exit(1);
}
int main(int argc, char** argv)
{
umask(0);
if (mkfifo(SERVFIFO, FILE_MODE) < 0 && errno != EEXIST)
syserr("mkfifo");
// try to open for write with no readers
int fdw = open(SERVFIFO, O_WRONLY | O_NONBLOCK);
if (fdw == -1)
perror("non-blocking open for write with no readers failed");
// create a reader - the process itself - non-blocking
int fdr = open(SERVFIFO, O_RDONLY | O_NONBLOCK);
if (fdr == -1)
syserr("non-blocking open for read no writers failed");
// try again to open for write but this time with a reader
fdw = open(SERVFIFO, O_WRONLY | O_NONBLOCK);
if (fdw == -1)
syserr("non-blocking open with readers failed");
printf("non-blocking open for write succeeded\n");
close(fdw);
close(fdr);
unlink(SERVFIFO);
}
That said, the fact that the `open` fails without blocking isn't all that useful. About the only thing you can do is continually try to open until you succeed and that kind of polling can be wasteful, and in the context of a long running program waiting for intermittent readers is sort of ridiculous.
One solution is that used above - open the FIFO for reading yourself - but this has its own problems.
If you use your FIFO write fd in your `select` statement it is always going to be writable...until it isn't. That is, because you are your own reader too, the FIFO writes will succeed until you fill the FIFO buffer with PIPE_BUF bytes. After that the FIFO won't be writable and your writes will fail with EAGAIN until a legitimate reader (i.e. not yourself) comes along, opens for reading, and starts draining the buffer.
By opening your own FIFO for reading and writing, you won't see an EOF from legitimate users when they close the FIFO. Since you are only concerned about writing this may not be an issue for you.
Another possible solution, which I have never tried, is to use inotify on your FIFO. You can monitor the inotify file descriptor in your `select` and determine when someone has opened the FIFO. Then you know you can safely open your end for writing. You would probably want to mask off open permissions on the FIFO so that you can be the only writer, if possible for your application.
FIFOs should be renamed PITAs for these funky semantics. If you can make the change, this is why the Unix gods bestowed domain sockets upon us mere mortals.
Problem
Is there a way (in C, or preferably in Perl) to determine whether a named pipe may be written - i.e. there is an active reading process It seems that if I open for write nonblocking, the open returns at once but a select for write also returns immediately. The goal is for the writing process to just carry on (i.e. skip sending) if the reading end is not ready