Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Jan 2019 02:56:13 +0100
From:      Willem Jan Withagen <wjw@digiware.nl>
To:        Alan Somers <asomers@freebsd.org>
Cc:        FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   Re: Using kqueue with aio_read/write
Message-ID:  <969d9a38-d3dd-78d0-c974-ba14ec4747db@digiware.nl>
In-Reply-To: <CAOtMX2iOy4Uf%2B9%2BuYhbX-wXJ68E57CjTW0aLPsa3dH__n4oP_w@mail.gmail.com>
References:  <8753521a-4555-ec2a-5efc-dee2660b4d9b@digiware.nl> <CAOtMX2iOy4Uf%2B9%2BuYhbX-wXJ68E57CjTW0aLPsa3dH__n4oP_w@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On 28/12/2018 02:47, Alan Somers wrote:
> On Thu, Dec 27, 2018 at 6:15 PM Willem Jan Withagen <wjw@digiware.nl> wrote:
>> Hi,
>>
>> Im trying to understand why I cannot get so code to work.
>> This is the smallest extract I can make to show my problem.
>>
>> I would expect the kevent() call to return every timeo tick.
>> Even if I tell it NOT to time-out I get these spurts of errors
>>
>> Since there is nothing to trigger the AIO-event, I would expect kqueue
>> to hold indefinitly.
>>
>> But it does not generate anything other than errors
>> And instead it repeatedly complains that there is a permission error:
>>     get_events_kevent: EV_Error(1) kevent(): Operation not permitted
>>
>> But I'm not getting where that would the case...
>>
>> Surely a pilot error, but I do overlook it al the time.
>> So suggestions are welcome.
>>
>> Thanx,
>> --WjW
>>
>> #include <aio.h>
>> #include <errno.h>
>> #include <fcntl.h>
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <string.h>
>> #include <sys/stat.h>
>> #include <sys/event.h>
>> #include <unistd.h>
>>
>> #define BUFFER_SIZE     512
>> #define MAX_EVENTS 32
>>
>> #define FILENAME "/tmp/aio_test"
>> char filename[256];
>> int fd;
>> int done = 0;
>>
>> void get_events_kevent(int fd, int kq)
>> {
>>       printf("get_events function fd = %d, kq = %d\n", fd, kq);
>>       int i = 0, errcnt = 0, err, ret, reterr, rev;
>>       int search = 1;
>>
>>       int timeout_ms = 10;
>>       struct timespec timeo = {
>>           timeout_ms / 1000,
>>           (timeout_ms % 1000) * 1000 * 1000
>>       };
>>       struct kevent filter[16];
>>       struct kevent changed[16];
>>
>>       EV_SET(&filter[0], fd, EVFILT_AIO,
>>               EV_ADD,
>>               0, 0, 0 );
>
> This is the first problem.  There's no need to explicitly set
> EVFILT_AIO on the kqueue.  It gets set by the aio_read(2) or similar
> syscall.  And this invocation wouldn't be correct anyway, because for
> AIO the ident field refers to the address of the struct aiocb, not the
> file descriptor.  If the only events you care about are AIO, then you
> can pass NULL as the filter argument to kevent.  I suspect this is the
> cause of your problem.  The kernel probably thinks you're trying to
> register for an aiocb that's outside of your address space or
> something like that.
>
>
>>       while (!done) {
>>           printf("+");
>>           rev = kevent(kq, filter, 1, changed, 16, 0); //&timeo);
>>           if (rev < 0) {
>>               perror("kevent error");
>>           } else if (rev == 0) {
>>               printf("T");
>>           } else {
>>               printf("rev(%d)\n", rev);
>>               if (changed[0].flags == EV_ERROR) {
>>                   errno = changed[0].data;
>>                   printf( "%s: EV_Error(%d) kevent(): %s\n", __func__, errno,
>>                       strerror(errno));
>>                   memset(&changed[0], 0, sizeof(struct kevent));
>>               } else {
>>                   err = aio_error((struct aiocb*)changed[0].udata);
>
> No need to call aio_error(2) after kevent(2) returns.  You can go
> straight to aio_return.  aio_error shouldn't hurt, but it isn't
> necessary.

According to kevent(2) calling kevent can return errors on the called 
aio_calls.
It then returns with EV_ERROR in flags, and errno is stored in the 
event.data.

But what would be going on when the event's flag contains EV_ERROR but 
event's data is still 0???

the udata field still seems to point to the aio data that was passed 
into the aio block when calling aio_read().

Should I ignore this as a non-error?

--WjW






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?969d9a38-d3dd-78d0-c974-ba14ec4747db>