0

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?

SD.
  • 1,432
  • 22
  • 38
  • What would you expect? When in your opinion `select` should return 0, if only a regular file is selected? – n. m. could be an AI Dec 10 '13 at 10:21
  • i have used select with socket, but not sure i can use it with regular file or not? my main concern is that as i am not writing to fd, it still prints "data available to read". please help. – SD. Dec 10 '13 at 10:26
  • @n.m. It would be quite useful for `select` to indicate that e.g. reading a network-mounted regular file would block. – user4815162342 Dec 10 '13 at 10:26
  • As has been noted this won't work for files. Normally this scenario would be handled with pipes though. Is there any particular reason you need the output as a regular file? – doynax Dec 10 '13 at 10:29
  • so n.m how can i check that only file with "fd" is available for writing or not? – SD. Dec 10 '13 at 10:32
  • 1
    @user4815162342 Even if the data is available in the buffer cache at the time of `select` there's no guarantee that the buffer cache won't get recycled between the return of `select` and the call to `read`. The choice in the operating system is to either always return "not readable" or "readable". Since lots of programs select on stdin (to handle a tty in a normal case) and would break when stdin was a file, only "readable" is a sensible choice. Furthermore, select doesn't guarantee that you won't block (think locks), only that you won't block indefinitely. – Art Dec 10 '13 at 10:33
  • 1
    Sorry, misread your comment. No, `select` does not work with network-mounted files. They are always considered available. – n. m. could be an AI Dec 10 '13 at 10:34
  • can i make fifo and use select on it? – SD. Dec 10 '13 at 10:39
  • @Saiyam Doshi: Have you tried pipe() instead? – doynax Dec 10 '13 at 10:41
  • @Art Good point about the race condition between the call to `select` and the call to `read`. I guess that's the reason AIO simply uses threads under the hood. – user4815162342 Dec 10 '13 at 10:42

1 Answers1

1

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.

Community
  • 1
  • 1
user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • Your answer seems write, just to confirm for select call i want to know that first argument is "number of fd's we want to poll" or "value of highest fd+1" , for example i have fd1 with value 4 and fd2 with value 5, so what should be value of first argument 3(fd1,fd2 and +1) or 6(highest value of fd+1) – SD. Dec 10 '13 at 10:36
  • 1
    @SaiyamDoshi The [manual on Linux](http://linux.die.net/man/2/select) makes it quite clear that *`nfds` is the highest-numbered file descriptor in any of the three sets, plus 1.* So, your second option is the correct one. – user4815162342 Dec 10 '13 at 10:45