c++linuxqtunixmkfifo

QSocketNotifier opened on a FIFO keeps firing even if I read everything


In my code I open a FIFO (created with mkfifo) and then I proceed to use a QSocketNotifier to receive notifications of incoming data, to read it while it arrives.

// create the FIFO
if(!mkfifo(SERIAL_FIFO, 0600)) {
    // nonblocking open (even open itself would block until a first write)
    in_fifo = ::open(SERIAL_FIFO, O_RDONLY | O_NONBLOCK);
    if(in_fifo >= 0) {
        // create notifier
        in_fifo_notifier = new QSocketNotifier(in_fifo, QSocketNotifier::Read, this);
        connect(&*in_fifo_notifier, &QSocketNotifier::activated,
                this, [this](QSocketDescriptor /*socket*/, QSocketNotifier::Type /*type*/){
            // copy all the available data
            char buf[4096];
            for(;;) {
                ssize_t rl = ::read(in_fifo, buf, sizeof(buf));
                if(rl <= 0) break;
                ::write(out_fd, buf, rl);
            }
        });
    }

The problem is that, whenever someone writes on the other end of the pipe, the signal keeps getting activated (with associated 100% CPU usage), even though every time I read all the data. Where's the problem?


Solution

  • Ultimately, this is just a variation over the problem described here, as Qt under the hood uses select/epoll machinery to implement QSocketNotifier. Opening the FIFO as O_RDWR fixes the problem.