Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can select() wait on regular file descriptors (non-sockets)?

Tags:

c

select

file-io

This is the code sample from "man select" plus a few lines to read an actual file which is being written to. I suspected that when the ./myfile.txt is written to, select would return that it can now read from that fd. But what happens is that select constantly returns in the while loop so long as the txt file exists. I want it to only return when new data is written to the end of the file. I thought that is how it should work.

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int
main(void)
{
    fd_set rfds;
    struct timeval tv;
    int retval;

    int fd_file = open("/home/myfile.txt", O_RDONLY);

   /* Watch stdin (fd 0) to see when it has input. */
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    FD_SET(fd_file, &rfds);

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

   while (1)
   {
     retval = select(fd_file+1, &rfds, NULL, NULL, &tv);
     /* Don't rely on the value of tv now! */

     if (retval == -1)
        perror("select()");
     else if (retval)
        printf("Data is available now.\n");
        /* FD_ISSET(0, &rfds) will be true. */
     else
        printf("No data within five seconds.\n");
   }

   exit(EXIT_SUCCESS);
}
like image 629
glutz Avatar asked Aug 10 '12 12:08

glutz


People also ask

How does select () work?

select() works by blocking until something happens on a file descriptor (aka a socket). What's 'something'? Data coming in or being able to write to a file descriptor -- you tell select() what you want to be woken up by.

What does select () do in C?

The select() function tests file descriptors in the range of 0 to nfds-1. If the readfds argument is not a null pointer, it points to an object of type fd_set that on input specifies the file descriptors to be checked for being ready to read, and on output indicates which file descriptors are ready to read.

What are the three file descriptors used in the select () call?

On success, select() and pselect() return the number of file descriptors contained in the three returned descriptor sets (that is, the total number of bits that are set in readfds, writefds, exceptfds).

How does select work in socket programming?

The select function returns the total number of socket handles that are ready and contained in the fd_set structures, zero if the time limit expired, or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, WSAGetLastError can be used to retrieve a specific error code.


1 Answers

Disk files are always ready to read (but the read might return 0 bytes if you're already at the end of the file), so you can't use select() on a disk file to find out when new data is added to the file.

POSIX says:

File descriptors associated with regular files shall always select true for ready to read, ready to write, and error conditions.

Also, as cnicutar pointed out in a now-deleted post, in general, you have to initialize the FD_SET on each iteration. In your code, you are monitoring one fd, and that fd is always ready, so the FD_SET is not in fact changing. However, if you have 5 decriptors to monitor, and select detects that only one is ready, then on the next iteration, only that one descriptor would be monitored (unless you reset the FD_SET). This makes using select tricky.

like image 180
Jonathan Leffler Avatar answered Nov 14 '22 02:11

Jonathan Leffler