Search code examples
cunixfile-ioposix-select

select() call on regular text file's file descriptor


I am facing strange issue, select return 1 value every time.

Below is my code:

Code:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

static int fd;

void *testThread(void* arg)
{
    fd_set set;
    struct timeval tv;
    int test = -1;

    char buf[8]={0};
    int ret = -1;

    while(1)
    {
        FD_ZERO(&set);
        FD_SET(fd,&set);

        /* Wait up to five seconds. */
        tv.tv_sec = 5;
        tv.tv_usec = 0;

        printf("waiting..\n");
        test = select(fd+1,&set,NULL,NULL,&tv); //FD_SETSIZE
        printf("Value of test = %d\n",test);
        perror("select:");

        if(test == 0)
            printf("No data available to read for last 5 sec.\n");
        else if(test < 0)
            printf("select() failed\n");
        else if(test > 0)
        {
            printf("data available to read\n");
            ret = read(fd,buf,sizeof(buf));
            printf("ret = %d\n",ret);
            printf("%s\n",buf);
            sleep(1);
        }

    }
}

int main()
{
    pthread_t id;
    int ret = -1;
    //FILE *fp = tmpfile();
    char *buf="Hello";
    fd = open("test.txt", O_CREAT |O_RDWR |  O_NDELAY);

    if(0 > fd)
    {
        perror("Failed to open tmp file\n");
        exit(-1);
    }

    printf("Fd %d\n",fd);

    pthread_create(&id,NULL,testThread,(void*)0);
    sleep(5);

    printf("Inside main\n");

    //ret = write(fd,buf,4);
    //printf("value of ret %d\n",ret);
    sleep(20);
    close(fd);

    return 0;
}

In this code i am facing strange behavior(may be i am wrong at some place), when i am not writing to fd, still select returns 1, and prints "data available to write". where i am wrong?


Solution

  • Unfortunately, select on regular files does not work the way you'd hope — they are always considered readable, even when reading them in reality blocks, as can be the case with remote-mounted partitions. The same applies to poll and equivalent multiplexors.

    The only portable way to perform a non-blocking read on an arbitrary file is by doing it in a separate thread. Another way is to use AIO, at the cost of additional complexity.