Reputation: 2014
I've to read program log file and to do that I wanted to use select() and read()
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd = -1;
fd_set fds;
struct timeval tv;
int rc;
char buffer[4096];
char * log_path = "/home/mich/a.txt";
if((fd = open(log_path,O_RDONLY) ) == -1 )
{
printf("error\n");
return -1;
}
while(1)
{
FD_ZERO(&fds);
FD_SET(fd,&fds);
tv.tv_sec = 2;
tv.tv_usec = 0;
rc = select(fd+1, &fds, NULL, NULL, &tv);
if (rc < 0) {
printf("failed\n");
continue;
} else if (rc > 0 && FD_ISSET(fd,&fds)) {
printf("read\n");
} else {
printf("timeout\n");
continue;
}
while ((my_getline(buffer,sizeof(buffer),fd)) > 0)
{
printf("%s",buffer);
}
}
close(fd);
}
my_getline is a function which uses read().
Output:
read
aaa
read
read
read
read
read
bbb
read
read
read
read
...
where aaa and bbb are lines from read file.
What is wrong in this program?
Upvotes: 2
Views: 1077
Reputation: 107839
select
tells you that there is something waiting on fd
. This doesn't have to be a line, it could be a single byte, or the information that the end of the file has been reached. Add puts("####");
at the end of the outer while
loop to see how your code processes the input file.
To see how to keep reading a file that other processes are appending to, look at the source code for one of the free implementations of the unix tail
utility (specifically its -f
option). The traditional implementation is to read the whole file, sleep for a small interval (1 second in tail
), and repeat from the position where you left off after the last read. A more modern, more reactive, less resource-consuming, but less portable approach uses a file change notification API (inotify under Linux, kqueue under *BSD, ...).
Upvotes: 2
Reputation: 239301
select()
tells you that a read()
won't block.
That includes the case where it will return 0
to indicate end-of-file, which presumably is what you're getting.
Upvotes: 4