kqueue and eof

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.
 
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?

Code:
#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;
}
 
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.
 
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.
 
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".

Code:
       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.
 
Back
Top