Question

I'm writing a program that when run from two separate bash sessions as two separate processes, opens a named pipe between the two to allow strings to be sent from one to the other.

When the process is first executed from one terminal, it checks stat(fname, buf) == -1 to see if a file at path fname exists and if not, creates it. The process then assumes that since it was the one to make the FIFO, it is the one that will be sending messages through it and continues accordingly.

After that occurs, the program can then be run from another terminal that should determine that it will be the receiver of messages through the pipe by checking stat(fname, buf) == -1. The condition should return false now, and stat(fname, buf) itself should return 0 because there exists a file at fname now.

But for reasons I am unable to discern, when the second process is run, stat(fname, buf) still returns -1. The variable errno is set to EFAULT. The man page for stat() only decribes EFAULT as "Bad address." Any help determining why the error occurs or what is meant by "Bad address." would be greaty appreciated.

I've verified that the file is indeed created by the first process as intended. The first process waits at the line pipe = open(fname, O_WRONLY); because it can't continue until the other end of pipe is opened.

Edit: The following is a self-contained implementation of my code. I have confirmed that it compiles and experiences the problem I described here.

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include    <string.h>

#define MAX_LINE 80
#define oops(m,x)   { perror(m); exit(x); }

int main(int argc, char const *argv[]) {
    char line[MAX_LINE];
    int pipe, pitcher, catcher, initPitcher, quit;
    struct stat* buf;

    char* fname = "/tmp/absFIFOO";
    initPitcher = catcher = pitcher = quit = 0;

    while (!quit) { 
        if (((!pitcher && !catcher && stat(fname, buf) == -1) || pitcher) && !quit) {
            // Then file does not exist
            if (errno == ENOENT) {
                // printf("We're in the file does not exist part\n");
                if (!pitcher && !catcher) {
                    // Then this must be the first time we're running the program. This process will take care of the unlink().
                    initPitcher = 1;
                    int stat;
                    if (stat = mkfifo(fname, 0600) < 0)
                        oops("Cannot make FIFO", stat);
                }
                pitcher = 1;

                // open a named pipe
                pipe = open(fname, O_WRONLY);

                printf("Enter line: ");
                fgets(line, MAX_LINE, stdin);

                if (!strcmp(line, "quit\n")) {
                    quit = 1;
                }

                // actually write out the data and close the pipe
                write(pipe, line, strlen(line));
                close(pipe); 
            }
        } else if (((!pitcher && !catcher) || catcher) && !quit) {
            // The first condition is just a check to see if this is the first time we've run the program. We could check if stat(...) == 0, but that would be unnecessary
            catcher = 1;

            pipe = open("/tmp/absFIFO", O_RDONLY);

            // set the mode to blocking (note '~')
            int flags;
            flags &= ~O_NONBLOCK;
            fcntl(pipe, F_SETFL, flags); //what does this do?

            // read the data from the pipe
            read(pipe, line, MAX_LINE);

            if (!strcmp(line, "quit\n")) {
                quit = 1;
            }

            printf("Received line: %s\n", line);

            // close the pipe
            close(pipe);
        }
    }
    if (initPitcher)
        unlink(fname);

    return 0;
}
Was it helpful?

Solution

You have this piece of code:

struct stat* buf;
...
if (((!pitcher && !catcher && stat(fname, buf) == -1)

When you call stat(), buf isn't initalized and there's no telling what it points to.

You must allocate some storage for it, so stat() has a valid place to store the result. The easiest thing is to just allocate it on the stack:

struct stat buf;
...
if (((!pitcher && !catcher && stat(fname, &buf) == -1)

OTHER TIPS

You have not shown your code, but EFAULT means 'bad address'. This indicates that you have not properly allocated (or passed) your buffer for stat or the filename (fname).

buf isn't initialised anywhere. What exactly do you expect to happen?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top