View Full Version : kqueue and eof
noobster
April 18th, 2009, 10:11
I am using a kqueue to asynchronously read from a file, but I couldn't figure out how to detect when the EOF has been reached. Does anyone know how to do that? Thanks.
Mel_Flynn
April 19th, 2009, 07:33
if ( event.flags & EV_EOF )
break; // or whatever you wanna do
noobster
April 19th, 2009, 09:58
Thanks for your reply. I have the code below, but it never detects the EOF. It simply reads all the bytes from the file and that's it. What am I missing?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/event.h>
#include <fcntl.h>
int main()
{
struct kevent ke;
off_t nread = 0;
int kq = kqueue();
int fd = open("filename", O_RDONLY | O_NONBLOCK);
EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
kevent(kq, &ke, 1, NULL, 0, NULL);
while (1)
{
memset(&ke, 0, sizeof(struct kevent));
if (kevent(kq, NULL, 0, &ke, 1, NULL) == -1)
{
perror("kevent");
exit(1);
}
if (ke.flags & EV_EOF)
{
printf("end of file!\n");
exit(1);
}
char buf[1024];
int n = read(ke.ident, buf, 1024);
if (n <= 0)
{
perror("read");
exit(1);
}
nread += n;
printf("nread: %lld\n", nread);
}
return 0;
}
Mel_Flynn
April 19th, 2009, 10:25
Why do you pass NULL as the changelist? I don't think you're getting any events. See if kevent returns 0, which is not an error (you didn't pass a changelist) and is equal to the number of events it triggered.
noobster
April 19th, 2009, 10:55
I am passing the changelist in the first kevent() call, and then in the second call I'm checking for events. I suppose I could combine this into one call, but it should work the way it is as well. I checked the return value of kevent() and it's never 0.
I appreciate your help.
Mel_Flynn
April 19th, 2009, 11:18
Never mind. EVFILT_READ on vnodes doesn't set EV_EOF cause you can detect going to EOF by reading ev.data. It contains "bytes left in file".
while (1)
{
char buf[64];
int n;
unsigned int left;
if (kevent(kq, NULL, 0, &ke, 1, NULL) == -1)
err(EXIT_FAILURE, "kevent");
if( ke.flags & EV_ERROR )
errc(EXIT_FAILURE, ev.data, "kevent");
if (ke.flags & EV_EOF)
{
printf("premature end of file!\n");
break;
}
n = read(ke.ident, buf, sizeof(buf));
if (n <= 0)
{
err(EX_FAILURE, "read");
}
nread += n;
printf("nread: %lld\n", nread);
left = (unsigned)ke.data;
if( left <= sizeof(buf) )
break; /* At EOF */
}
P.S.: probably better to use an off_t for left, and a constant instead of sizeof(buf), so your code compiles with WARNS=3.
noobster
April 19th, 2009, 11:26
Thanks, that is exactly what I was looking for.
vBulletin® v3.8.7, Copyright ©2000-2012, vBulletin Solutions, Inc.