Using kqueue with aio_read/write
Willem Jan Withagen
wjw at digiware.nl
Wed Jan 2 01:56:18 UTC 2019
On 28/12/2018 02:47, Alan Somers wrote:
> On Thu, Dec 27, 2018 at 6:15 PM Willem Jan Withagen <wjw at 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
More information about the freebsd-hackers
mailing list