Thread: Nonblocking FIFO

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    15

    Nonblocking FIFO

    Greetings,
    Simple issue, but my own research has turned up nothing.

    I'm attempting to create an intra-process communication system to create a communication & control program for a server daemon running in the background.

    Now, I've got the FIFO working properly, it can read and write commands rather well, only problem is, the entire system is rigged using FILE and fcommands, and all of my options to set the FIFO to nonblocking seem to deal with file descriptor integers, where FILE is an _IO_STREAM (or something like that)...

    So my question, is there is possible way to make this FIFO nonblocking in such a way that I don't need to completely rewrite the module that I've made thusfar?

  2. #2
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    maybe something like this: fileno

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by @nthony View Post
    maybe something like this: fileno
    What he said. Use fileno() to get the fd associated with the FILE object, then use fcntl() to make it non-blocking.

  4. #4
    Registered User
    Join Date
    Apr 2007
    Posts
    15
    I'm using the functions in this order (example with limited details to prevent confusion)
    Code:
    main ( )
    {
      initalize_fifo( )
      for ( ;; )
      {
         handle_fifo( );
      }
    }
    
    initalize_fifo( )
    {
      mkfifo( FIFO_FILE, 0666 );
      <fifo clearing code>
    }
    
    handle_fifo( )
    {
    FIFO_DATA * fifo;
    fifo = read_fifo( );
    
    <more processing stuff here>
    }
    
    read_fifo( )
    {
      FILE * fp;
      fp = fopen( filename, "rw" );
      fcntl( fileno( fp ), F_SETF, FNDELAY );
    
      <file reading code here>
    }
    and still it blocks, I considered using fcntl on FIFO creation, but mkfifo() doesn't return the fd, just creates it in the filetree. I may be able to rewrite it to use a global variable for the fifo's FILE struct.... is that what I need to do? or am I missing something here? it seems that right when it opens it blocks, not processing anything after it, and I can't exactly set that flag before it opens.... right?

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > fp = fopen( filename, "rw" );
    Is "rw" even valid for fopen?
    Does it return an error?

    Why would you want a bi-directional thing for a fifo anyway?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    I think that will just be read as "read-only" as in the case with "rb", I remember reading somewhere that in order to be compatible with ANSI, fopen only reads the first character of the mode argument (and anything after a "+").

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Mmm, maybe. Not according to this: http://www.opengroup.org/onlinepubs/...ons/fopen.html
    The mode argument points to a string. If the string is one of the following, the file shall be opened in the indicated mode. Otherwise, the behavior is undefined.

    r or rb
    Open file for reading.
    w or wb
    Truncate to zero length or create file for writing.
    a or ab
    Append; open or create file for writing at end-of-file.
    r+ or rb+ or r+b
    Open file for update (reading and writing).
    w+ or wb+ or w+b
    Truncate to zero length or create file for update.
    a+ or ab+ or a+b
    Append; open or create file for update, writing at end-of-file.
    But you're right by this one: http://www.opengroup.org/pubs/online...xsh/fopen.html
    The argument mode points to a string beginning with one of the following sequences:
    Anyway, it won't do what is intended.

    Perhaps the OP wants mode r+ or w+ or a+.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Teegtahn View Post
    Code:
      fcntl( fileno( fp ), F_SETF, FNDELAY );
    NDELAY is not what you want. You need to read the flags with F_GETFL, then OR in the O_NONBLOCK bit, then set the flags back with F_SETFL.

    Code:
    int flags;
    int fd;
    
    fd = fileno(fp);
    flags = fcntl(fd, F_GETFL);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);

  9. #9
    Registered User
    Join Date
    Apr 2007
    Posts
    15
    I'd be less irritated if I didn't really need this, but it's still blocking, I've changed the code to the following (for the read_fifo)

    Code:
    FIFO_DATA *read_fifo( char filename[256] )
    {
            int fd, flags;
            FILE *  fp;
    
            FIFO_DATA *    fifo;
            CREATE( fifo, FIFO_DATA, 1 );
    
            if ( ( fp = fopen( filename, "r" ) ) == NULL )
            {
                    perror( filename );
                    exit( 1 );
            }
    
            fd = fileno( fp );
            flags = fcntl( fd, F_GETFL );
            fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    
    <FIFO Reading Code Here>
    }
    I really think it's blocking on fopen(), since it won't throw any error messages I put in between that and my first getc( fp ) call.

    The process runs fine until I tell the server to try to handle the fifo.. it locks, and waits for me to issue a command from the client I wrote...

    Mabye I should just rewrite it using open() so I can just pass the damn flag right when I open it.

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    You can't open a FIFO using fopen() in this way -- you want it to open immediately, the OS will only open it once the writer side has opened it. You have no choice but to open it using open(). But at least you can turn this fd into a FILE object once you do it:

    Code:
    int fifo_fd = open(fifo_path, O_RDONLY | O_NONBLOCK);
    FILE *fp = fdopen(fifo_fd, "r");
    Whoops, originally forgot the "r" argument.
    Last edited by brewbuck; 05-02-2007 at 06:14 PM.

  11. #11
    Registered User
    Join Date
    Apr 2007
    Posts
    15
    my read statements no longer read from the pipe correctly, client returns a Broken Pipe error, and the server returns a (null) string...

    I'm investigating myself, but it's no longer blocking.

    Thank you

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Teegtahn View Post
    my read statements no longer read from the pipe correctly, client returns a Broken Pipe error, and the server returns a (null) string...
    The server isn't closing/reopening the pipe repeatedly, is it?

  13. #13
    Registered User
    Join Date
    Apr 2007
    Posts
    15
    not in one read cycle...

    read_fifo opens and closes it once during it's run, but after it's read, the fifo is closed, the data is preserved, processed and the system starts again... it's running inline with a few other read/write modules

  14. #14
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Teegtahn View Post
    not in one read cycle...

    read_fifo opens and closes it once during it's run, but after it's read, the fifo is closed, the data is preserved, processed and the system starts again... it's running inline with a few other read/write modules
    The only reason you'd be getting a broken pipe signal in the client would be the client trying to write to a pipe that the server side had already closed.

  15. #15
    Registered User
    Join Date
    Apr 2007
    Posts
    15
    after I finish reading the fifo... does it clear itself? or am I looking at a whole new set of problems trying to read from this thing on a continous basis?

    Edit:
    I've been unconditionally accepting advice here, since I've never delt with files, and you guys seem to know your way around sockets and fds and stuff... but does it matter that I had it working (albiet that it was blocking) before I flipped to open() and openfd? it was reading the fifo fine

    Edit2:
    Got the pipe reading again... but I can't get it to reset to the start of the pipe, I only feed the server one line at a time... so I really only need to read line 1... my problem is I can't get the pointer to get back to the start, it just keeps reading past EOF, returning NULL forever.

    Edit3:
    Found fseek(), I'm learning I think. now a headache handling the fifo reading & clearing again.
    My pipe is dumping a lot of &#255;&#255;&#255;&#255;&#255;&#255;&#255;&#255;&# 255;&#255;&#255;&#255;&#255;&#255;&#255;&#255;&#25 5;&#255;&#255;&#255;&#255;&#255;&#255;&#255;&#255; &#255;&#255;&#255;&#255; lines after using fseek( fifop, 0, SEEK_SET );
    0 is the beginning of the file... right?

    Edit4:
    0 is beginning of file, yes.
    the character is value -1 (EOF.. I think.) so I've applied a check for if c = -1;

    Problem with FIFOs solved. Thank you all for your help
    Last edited by Teegtahn; 05-02-2007 at 09:27 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. select system call with FIFO fd.
    By vlrk in forum Linux Programming
    Replies: 0
    Last Post: 05-11-2009, 04:27 AM
  2. simultaneously waiting for data on FIFO and UDP using select call
    By yogesh3073 in forum Networking/Device Communication
    Replies: 2
    Last Post: 01-05-2007, 09:53 AM
  3. working with FIFO files
    By icebabe in forum C Programming
    Replies: 6
    Last Post: 05-06-2006, 11:35 AM
  4. help! fifo read problem
    By judoman in forum C Programming
    Replies: 1
    Last Post: 08-16-2004, 09:19 AM
  5. FIFO list
    By Lillian176 in forum C Programming
    Replies: 4
    Last Post: 04-13-2003, 10:45 PM