Link to home
Start Free TrialLog in
Avatar of waslap
waslap

asked on

FIFO O_RDWR

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.
Avatar of dhm
dhm

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?
Avatar of waslap

ASKER

I'm using Lunix. Might be that I'm doing something really stupid causing this.
Could you show the rilevant code?
-julio
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 warthog.foobar.com 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)

int
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

[...]
ASKER CERTIFIED SOLUTION
Avatar of Sigma031497
Sigma031497

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of waslap

ASKER

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! :-)