When I open a FIFO with O_RDWR and I write to it and then do a select on it to read, select immediately returns saying there is something. When I read, I get what I've just written. This continues untill the process on the other side reads from the FIFO. Thus, the writer reads his own writing numerous times. It isn't removed from the FIFO however until the other side reads it. Is there some way around this.
Who is Participating?
Sigma031497Connect With a Mentor Commented:
This is correct behaviour for a fifo - it doesnt care who is reading and who is writing to it. This makes them inappropriate for two way communications - they are usually used when a signle program reads from it, and a lot of programs write to it.

If you want two-way communications either use two fifos - one for incomming and one for outgoing messages (yuck) - or use unix domain sockets, which are designed with this particular use in mind.

This sounds like an OS bug.  I just wrote a quickie read/write program under Solaris-2.5.1 and it behaves as expected: once you read the message out of the FIFO, it's gone -- nobody else gets it (including the process that *wrote* it there in the first place.)

What OS are you using?
waslapAuthor Commented:
I'm using Lunix. Might be that I'm doing something really stupid causing this.
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

Could you show the rilevant code?
I tried the program below on one of my Linux boxes, but got nothing unusal.  Are you doing something different?  Or maybe just using a different version of the OS?

dhm@warthog[77]$ uname -a
Linux 2.0.26 #9 Sun Apr 20 21:38:24 PDT 1997 i586

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#define ASSERT(cond)    do if (!(cond)) { \
                            int e = errno; \
                            printf( "Assertion failed: " #cond " errno %d\n", \
                                    e ); \
                            exit( e ); \
                        } while (0)

main( int argc, char **argv )
    int      fd;
    ssize_t  wrote;
    fd = open( "/tmp/fifo", O_RDWR );
    ASSERT( fd != -1 );

    wrote = write( fd, "Hello, world\n", 13 );
    ASSERT( wrote == 13 );

    for ( ; ; ) {
        int              n;
        fd_set           readable;
        struct timeval   one_second;

        FD_ZERO( &readable );
        FD_SET( fd, &readable );
        one_second.tv_sec = 1;
        one_second.tv_usec = 0;
        n = select( fd + 1, &readable, 0, 0, &one_second );

        ASSERT( n != -1 );

        if (n == 1) {
            char     buf[8];
            ssize_t  red;
            red = read( fd, buf, sizeof(buf) );
            ASSERT( red != -1 );
            printf( "A: read %d: [%.*s]\n", red, red, buf );
        } else {
            puts( "A: nothing readable" );

    exit( 0 );

Here's what happens when I run it:

dhm@warthog[79]$ mkfifo /tmp/fifo
dhm@warthog[80]$ ./a.out
A: read 8: [Hello, w]
A: read 5: [orld
A: nothing readable
A: nothing readable
A: nothing readable

waslapAuthor Commented:
OK. If it is FIFO's behaviour, why does select keep on saying that there is still something to read even after the original writer did read it. It only stops saying that after the real reader on the other side has read from the FIFO.
In my test program, select *doesn't* return "readable."  Are you select()ing on other conditions (writable, exceptions) as well as readable?  Maybe it's another condition that's unblocking the select(). If your read() is actually failing but you don't notice, then whatever was read on the first pass will still be in the buffer; if you print it out, it'll look like you got the same message over and over again.
Whoops, mommy did always say to read things carefully. I'm not sure why you are having problems with select, dim's ideas sound pretty good. But you know, you dont actually need to use select (unless you want to do something useful while waiting for input). A read on a fifo will block until another process writes to it. Also, if you dont accept my answer, you'd do well to reject it (I know this sounds awfully harsh), this will give dim a chance.
That's dHm, not dIm! :-)
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.