Vasil Kalchev
Vasil Kalchev

Reputation: 201

Continuous reading of FIFO using select()

I am trying to read a FIFO in the background (using a thread) while my main program is running inside an infinite loop. I want to use select() because otherwise the processor runs at 100%, but the appropriate example I found isn't working. This is the example code:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>

int main()
{
    mkfifo("FIFO", 0666);

    fd_set readCheck;
    fd_set errCheck;
    char buffer[64];
    struct timeval timeout;
    int rv;

    int fd = open("FIFO", O_RDONLY | O_RSYNC);

    FD_ZERO(&readCheck);
    FD_ZERO(&errCheck);

    while (1) {
        FD_SET(fd, &readCheck);
        FD_SET(fd, &errCheck);

        timeout.tv_sec = 1;
        timeout.tv_usec = 0;

        rv = select(fd, &readCheck, NULL, &errCheck, &timeout);
        if (rv < 0) {
            printf("Select failed\r\n");
            break;
        }

        if (FD_ISSET(fd, &errCheck)) {
            printf("FD error\r\n");
            continue;
        }

        if (FD_ISSET(fd, &readCheck)) {
            memset(buffer, 0, sizeof(buffer));
            rv = read(fd, buffer, sizeof(buffer));
            if (rv < 0) {
                printf("Read failed\r\n");
                break;
            }
            printf(buffer);
            buffer[64] = '\0';
        }
    }
    close(fd);

    return 0;
}

When I write to the FIFO file nothing happens, but using cat FIFO prints the contents. What can be the problem?

Upvotes: 1

Views: 1750

Answers (2)

David Ranieri
David Ranieri

Reputation: 41017

Your buffer is declared as

char buffer[64];

using

buffer[64] = '\0';

you are writing out of bounds.

Change

buffer[64] = '\0';

to

buffer[rv] = '\0';

Upvotes: 1

Karthikeyan.R.S
Karthikeyan.R.S

Reputation: 4041

You have to give the first argument as one higher than the last opened file descriptor. From the man page page of select,

nfds is the highest-numbered file descriptor in any of the three sets, plus 1

Change this line,

rv = select(fd, &readCheck, NULL, &errCheck, &timeout);

to

rv = select(fd+1, &readCheck, NULL, &errCheck, &timeout);

If you are not mentioning this,then select will not check your descriptor so you will not the file descriptor is ready for reading.

Upvotes: 2

Related Questions