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

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, Jan 1, 2019 at 6:56 PM Willem Jan Withagen <wjw@digiware.nl> wrote:
>
> 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

Are you sure you bzero()ed your aiocb before initializing it?  Any
stack garbage that was present in its
aio_sigevent.sigev_notify_kevent_flags field will be dutifully copied
into the returned kevent.  And in any case, the definitive way to get
the final status of a completed aio operation is with aio_return.
-Alan



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAOtMX2ics595SQTDR=ORF8YCTOgm9JSk-Nv1T89O6iCOp5O4fg>