using QTextStream to read stdin in a non-blocking fashion


Using Qt, I'm attempting to read the contents of the stdin stream in a non-blocking fashion. I'm using the QSocketNotifier to alert me when the socket has recieved some new data. The setup for the notifier looks like this:

QSocketNotifier *pNot = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this);
connect(pNot, SIGNAL(activated(int)), this, SLOT(onData()));

The onData() slot looks like this:

void CIPCListener::onData()
    qDebug() << Q_FUNC_INFO;
    QTextStream stream(stdin, QIODevice::ReadOnly);

    QString str;

        fd_set stdinfd;
        FD_ZERO( &stdinfd );
        FD_SET( STDIN_FILENO, &stdinfd );
        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = 0;
        int ready = select( 1, &stdinfd, NULL, NULL, &tv );
        if( ready > 0 )
            str += stream.readLine();

    qDebug() << "Recieved data:" << str;

As you can see I'm attempting to use the select() system call to tell me when I've run out of data to read. However, in practise what is happening is the select() call returns 0 after I've read the first line of text. So, for example, if I write 5 lines of text to the process's stdin stream, I only ever read the first line.

What could be the problem?

8/13/2009 12:52:01 PM

Accepted Answer

Line buffering.

Default is flushing after a "\n". If you write 5 lines to your process, your slot gets called 5 times. If you want to avoid that, you have to call setbuf(stdin, _IOFBF). But even then it is not guaranteed you can read arbitrarily large amounts of data in one chunk.

Edit: It would probably better to use QTextStream::atEnd() instead of select, since QTextStream has its own internal buffers.

8/13/2009 3:42:28 PM

I've found and example in other answer that fits almost to this question and with complete and simple code:

I've used it to implement a QT console based app with a textual menu to choose on user selection.

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow