11

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);
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
glutz
  • 1,889
  • 7
  • 29
  • 44
  • So what is your question ? **Who said `select` should only work on sockets** ? – cnicutar Aug 10 '12 at 12:45
  • question edited. sorry for confusion. – glutz Aug 10 '12 at 12:49
  • `select` can be used on _any_ file-type descriptor, doesn't matter if it's a socket, file or pipe or any similar descriptor. However, you can not use it to monitor when a file has been written to, for that you have to use something OS specific, like on Linux you can use [inotify](http://en.wikipedia.org/wiki/Inotify). – Some programmer dude Aug 10 '12 at 12:51
  • i understand the first part of your comment. But the i thought that the purpose of selecting on a socket was basically just listening for when data was written to the socket. How is it different for a file? – glutz Aug 10 '12 at 12:53

1 Answers1

18

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.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 3
    AFAIK `poll` cant be used to watch regular file for changes as well. So the only way to go is `inotify`? The problem is `inotify`-based solution works with filepath, not with file-descriptors that are already open. – St.Antario Jan 28 '19 at 17:20