2

I want to create a server process and a client process -for an optional class assignment- and make them communicate with each other. The professor told us that:

1)we must use O_NONBLOCK

2)we must create 2 FIFOs, one for reading only and one for writing only

3)we can't use sockets

So, I created 2 FIFOs in server process and I tried to open them but the open for WRONLY returned "No such device or address".

server process:

......

if( mkfifo("fifo1", PERMS) < 0 && errno != EEXIST)
{
    perror("can't create FIFO (read)");
    exit(EXIT_FAILURE);
}
if( mkfifo("fifo2", PERMS) < 0 && errno != EEXIST )
{
    perror("can't create FIFO (write)");
    exit(EXIT_FAILURE);
}

if( (readfd = open("fifo1", O_RDONLY | O_NONBLOCK)) < 0)
{
    perror("console: can't open read FIFO");
    exit(EXIT_FAILURE);
}
if( (writefd = open("fifo2", O_WRONLY | O_NONBLOCK)) < 0)
{
    perror("coord: can't open write FIFO");
    exit(EXIT_FAILURE);
}

client process:

.....

if( (readfd = open("fifo2", O_RDONLY | O_NONBLOCK)) < 0)
{
    perror("console: can't open read FIFO");
    exit(EXIT_FAILURE);
}
if( (writefd = open("fifo1", O_WRONLY | O_NONBLOCK)) < 0)
{
    perror("console: can't open write FIFO");
    exit(EXIT_FAILURE);
}

while( fgets(buffer, 100, stdin) )  //char buffer[100];
{
    n = strlen(buffer);
    w = write(writefd, buffer, n);

    memset(buffer, 0, 100);
}

I looked for a solution online and I found out this answer, which explains fine what goes wrong, but doesn't propose a way to fix the issue. I looked online again and found select() and it looked like it can provide a solution, but I had some trouble understanding how exactly it works.

Is it possible to use select() in order to fix this issue?

Community
  • 1
  • 1
Fotis Sk
  • 313
  • 2
  • 10

2 Answers2

3

A straightforward solution is to open fifo for writing in a blocking mode (it will block until the other end is opened for reading), and make it nonblocking afterwards:

    writefd = open(fifo_name, O_WRONLY);
    fcntl(writefd, F_SETFL, O_NONBLOCK);

PS: I strongly recommend against busy waiting.

user58697
  • 7,808
  • 1
  • 14
  • 28
0

You cannot open a FIFO for writing without blocking unless a reader already has the FIFO open. The simplest fix is just to wait a second and repeat the open if it returns ENXIO. Repeat until the other side is running.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • So, you are proposing a simple while(1) or for(;;) loop with the open for write inside. I suppose it is a good workaround, since it happens only once at the beginning. Thanks – Fotis Sk Apr 13 '17 at 22:32
  • @FotisSk Yeah. Add a comment explaining the rationale and why it's not worth more effort. – David Schwartz Apr 13 '17 at 22:33
  • Yes, I will. By the way, something that just came up to me. Is it "ok" if a read (or some other random command) returns -1 to ignore it and read again? Thanks in advance for your help!! – Fotis Sk Apr 13 '17 at 23:59
  • @FotisSk It depends what the error is. For example, it's fine if it's `EINTR`. But most errors are fatal. – David Schwartz Apr 14 '17 at 00:11