2

'Server' program side:

#define RESP_FIFO_NAME "response"

/* Global Variables */
char *cmdfifo = CMD_FIFO_NAME; /* Name of command FIFO. */
char *respfifo = RESP_FIFO_NAME; /* Name of response FIFO. */

int main(int argc, char* argv[]) {
int infd, outfd; /* FIFO file descriptors. */

... // blah blah other code here

/* Create command FIFO. */
if (mkfifo(cmdfifo, FIFO_MODE) == -1) {
    if (errno != EEXIST) {
        fprintf(stderr, "Server: Couldn’t create %s FIFO.\n", CMD_FIFO_NAME);
        exit(1);
    }
}

/* Create response FIFO. */
if (mkfifo(respfifo, FIFO_MODE) == -1) {
    if (errno != EEXIST) {
        fprintf(stderr, "Server: Couldn’t create %s FIFO.\n", RESP_FIFO_NAME);
        exit(1);
    }
}
/* Open the command FIFO for non-blocking reading. */
if ((infd = open(cmdfifo, O_RDONLY | O_NONBLOCK)) == -1) {
    fprintf(stderr, "Server: Failed to open %s FIFO.\n", CMD_FIFO_NAME);
    exit(1);
}

        /* Open the response FIFO for non-blocking writes. */
if ((outfd = open(respfifo, O_WRONLY | O_NONBLOCK)) == -1) {
            fprintf(stderr, "Server: Failed to open %s FIFO.\n", RESP_FIFO_NAME);
            perror(RESP_FIFO_NAME);
            exit(1);
        }

The program prints an output of:

Server: Couldn’t create response FIFO.

I understand very little on FIFOs as my professor didn't teach it. This was all I was able to manage from reading his examples and lecture notes. I tried without O_NONBLOCK flag but that just causes the program to hang, so it is required. I don't understand why the read FIFO is fine but the write FIFO fails to open.

tshepang
  • 12,111
  • 21
  • 91
  • 136
ICantNameMe
  • 93
  • 1
  • 1
  • 7
  • You should report the name used in the `mkfifo()` call in the error message — so `respfifo` rather than `RESP_FIFO_NAME`. What FIFOs exist in the current directory (of the program when it is run)? Are you sure you want angle brackets included in the FIFO name (or is the error message from a different version of the code)? You could include `errno` and `strerror(errno)` in the output; this would help diagnose what the problem is (EEXIST vs EPERM vs ...). – Jonathan Leffler May 06 '13 at 05:24
  • Use `perror` or `strerror` to know what is the exact error. – Thomas Ruiz May 06 '13 at 05:27
  • `RESP_FIFO_NAME` is a preprocessor `#define`'d macro constant. I will add that now. I assumed it did not matter as it was simply a string literal with direct text replacement. Yeah, I'll use perror right now and see what the actual problem is. – ICantNameMe May 06 '13 at 05:27
  • `perror(RESP_FIFO_NAME)` outputs `: No such device or address` which is apparently `ENXIO` – ICantNameMe May 06 '13 at 05:30
  • Intriguing: ENODEV is not listed as a possible error from `mkfifo(2)` on Mac OS X. Have you done any `chdir()` operations? I see that dropping the angle brackets doesn't change the result. What is `FIFO_MODE`? Does the command FIFO already exist? – Jonathan Leffler May 06 '13 at 05:37
  • `FIFO_MODE` is `0644` = `rw-r--r--`. I didn't use any `chdir` whatsoever, all files I am dealing with are in the same directory. I just created `cmdfifo` at the top of main. It may exist already from previous program executions. If I move the `open` command for `respfifo` down as far as possible, I instead get an error on `read(infd, msgbuf, MSGSIZE+1) == -1`, which returns `Resource temporarily unavailable` from the call to `perror`. – ICantNameMe May 06 '13 at 06:03
  • Actually the first execution gives me `No such device or address`, then if I run it again without deleting the FIFO file, I get a `Resource temporarily unavailable` error. – ICantNameMe May 06 '13 at 06:04

1 Answers1

4

From the man-page :

A process can open a FIFO in non-blocking mode. In this case, opening for read only will succeed even if noone has opened on the write side yet; opening for write only will fail with ENXIO (no such device or address) unless the other end has already been opened.

You should open this one in the 'client'.

Thomas Ruiz
  • 3,611
  • 2
  • 20
  • 33
  • Okay. I was confused by his instructions then, because he said: `/* Create and appropriately open the command and reply FIFOs. */` Which was before the process fork to create the faux 'Client' (child) process. I opened it in the Client process, but that occurs later in the program... – ICantNameMe May 06 '13 at 05:38
  • That's interesting — but would affect opening the FIFO, not creating it which is apparently where the trouble is occurring. @ICantNameMe: are you sure it is your `mkfifo()` that is failing? Did you by any chance copy and paste an error message block without changing the message? – Jonathan Leffler May 06 '13 at 05:40
  • It's not the `mkfifo` that's failing, it's the `open` command for `O_WRONLY | O_NONBLOCK` that gives me a `ENXIO: no such device or address error`. I don't know why it's giving me this error because I can't access the client file yet, so I guess that means I have to move this down further in the program until after the fork, otherwise there's nobody to read what I'm writing? – ICantNameMe May 06 '13 at 05:43
  • I thought that too, that's why you have to open this fifo in the client, i guess. – Thomas Ruiz May 06 '13 at 05:46
  • @ICantNameMe: your code snippet is totally confusing if it is the `open()` (which you don't show) that is failing — that warrants the down-vote. The description of the error message that Thomas found is entirely apposite for opening a FIFO for write only with O_NONBLOCK. Maybe you should wait to open the response FIFO for writing until you've got a client with the command FIFO open for writing? Or maybe you don't want O_NONBLOCK... – Jonathan Leffler May 06 '13 at 05:53
  • I'm sorry I totally forgot to include that. I thought I did for some reason. It's there now. Sorry for the confusion. – ICantNameMe May 06 '13 at 06:04