Michael F. Robbins on Mon, 24 Jun 2002 14:00:11 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[PLUG] C++, FIFOs, getline, and O_NDELAY


I'm writing a c++ app to read a command stream from a fifo.  Commands
are delimited by newlines.  The app must be able to process other tasks
(running in a while loop) if there is no data incoming from the fifo. 
Right now, I'm using ifstream's rdbuf()->fd() to get the file descriptor
so I can use poll() on the fifo.  When there is a read event, I do an
ifstream::getline() on the input stream class.  The problem occurs when
the sending program sends two lines at once, i.e. before the listener
task is run again.  The getline() is only called once for each poll()
that returns positive, however sometimes really two or more getline()s
are needed.  I would have thought that checking for the POLLIN event
would have returned true since there were more data left to read. 
However, my guess is that the ifstream class has an internal buffer
which has the next command inside, so the poll() returns false.

Any ideas?  Right now I'm looking at setting O_NDELAY on the file
descriptor.  This would certainly allow a simple read() function to work
on it, but would the getline() work correctly?

Here's the code in question:
------
// includes omitted for sanity

int main(int argc, char *argv[])
{
  ifstream fifoIn("/path/to/fifo");
  int fifoInID = fifoIn.rdbuf()->fd();
  pollfd fifoInPollFD = {0, 0, 0};
  fifoInPollFD.fd = fifoInID;
  fifoInPollFD.events = POLLIN;

  char lastCommandC[1024];
  String lastCommand;
  
  while(1) {
    // Other stuff must be free to happen here
    // if there are no new commands
    
    // Check for tasks on message queue and process them.
    fifoInPollFD.events = POLLIN;
    fifoInPollFD.revents = 0;

    // 10 millisecond timeout
    if(poll(&fifoInPollFD, 1, 10) > 0) {

      // Grab a line, stick it in lastCommandC, and
      // convert it to a String class
      fifoIn.getline(lastCommandC, sizeof lastCommandC, '\n');
      lastCommandC[sizeof lastCommandC - 1] = '\0';
      lastCommand = lastCommandC;

      // No, this is not the error.  The dispatch function
      // is defined and works well.
      cerr << "Dispatch: " << lastCommand << endl;
      dispatch(lastCommand);

      if(fifoIn.eof()) {
	cerr << "eof on input fifo" << endl;
	exit(0);
      }
    }
  } // close while loop
  return 0;
}
------

Thanks,

Michael F. Robbins
mike@gamerack.com

Attachment: signature.asc
Description: This is a digitally signed message part