>     it gets worse -- when i change my loop to be:
> 
>     while (1) {
> 
>             fifo = open(fifoPath, O_RDONLY | O_NONBLOCK);
>             cread = read(fifo, buf, sizeof(buf));
>             if (cread > 0) do_something();
>             close(fifo);
>             usleep(100000);
>     }
> 
>     anybody who tries to open the write end of the fifo ends up hanging
> ..

It's a little messier than I hoped.  As long as no one has opened the
FIFO for write read returns a zero with errno clear.  If you don't have
time slicing turned on for the threads you'll hang forever.

You'll have to do something like this:

#include <unistd.h>

#include <sys/stat.h>
#include <sys/types.h>

#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>

struct threadstuff {
        int rfid, wfid;
        const char *name;
};

static void *
reader(void *arg) {
        int flags;
        ssize_t r;
        char buff[32];
        int cr;

        struct threadstuff *pts = (struct threadstuff *)arg;

        fprintf(stderr, "Opening %s for read, non-blocking...\n", pts->name);

        pts->rfid = open(pts->name, O_RDONLY | O_NONBLOCK);

        fprintf(stderr, "reader got fid %d, setting to blocking...\n", pts->rfid);

        (void)fcntl(pts->rfid, F_GETFL, &flags);
        flags &= ~O_NONBLOCK;
        (void)fcntl(pts->rfid, F_SETFL, &flags);

        fprintf(stderr, "Trying to read something from the FIFO...\n");

        cr = 0;

        /*
         * You better have round robin turned on here or be sure
         * the writer is of higher priority or you'll just buzz
         * away the CPU.
         */

        do {
                errno = 0;
                r = read(pts->rfid, buff, sizeof(buff) - 1);

                if (errno == 0 && r == 0) {
                        /* No one has the FIFO open for write.
                         * You should delay here (or preferably synchronize) 
                         * to avoid busy waiting.
                         */
                        cr++;
                        fprintf(stderr, "%s(%3d) No writer yet.\r",
                                ((cr % 5) == 1) ? "\n" : "", cr);
                }
        } while (r == 0);

        if (r < 0) {
                perror("Read of FIFO");
        } else {
                buff[r] = 0;
                fprintf(stderr, "Read \"%s\".\n", buff);
        }

        return 0;
}

static void *
writer(void *arg) {
        char something[] = "Something";

        struct threadstuff *pts = (struct threadstuff *)arg;

        fprintf(stderr, "Opening %s for write\n", pts->name);

        pts->wfid = open(pts->name, O_WRONLY);

        fprintf(stderr, "writer got fid %d.\n", pts->wfid);

        write(pts->wfid, something, sizeof(something));

        return 0;
}

int
main(int ac, char *av[]) {
        pthread_t r, w;
        void *value;

        struct threadstuff ts;

        ts.name =  "./my_fifo";
        ts.rfid = ts.wfid = -1;

        (void)unlink(ts.name);
        (void)mkfifo(ts.name, 0666);

        pthread_create(&r, 0, reader, (void *)&ts);
        pthread_create(&w, 0, writer, (void *)&ts);

        pthread_join(r, &value);
        pthread_join(w, &value);

        if (ts.rfid != -1)
                (void)close(ts.rfid);

        if (ts.wfid != -1)
                (void)close(ts.wfid);

        return 0;
}

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to