From owner-freebsd-hackers@freebsd.org Wed Jan 2 02:24:03 2019 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id EC9F91431AA1 for ; Wed, 2 Jan 2019 02:24:02 +0000 (UTC) (envelope-from asomers@gmail.com) Received: from mail-lf1-f66.google.com (mail-lf1-f66.google.com [209.85.167.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 646516DDBD for ; Wed, 2 Jan 2019 02:24:02 +0000 (UTC) (envelope-from asomers@gmail.com) Received: by mail-lf1-f66.google.com with SMTP id a16so20139555lfg.3 for ; Tue, 01 Jan 2019 18:24:02 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=vY74+7co0icbywgT7sxgby+Yz0DI6fqnZHGrdAWS17g=; b=IVdUz3WAKOjAiwjURPcbiI/I555OZS7dtEa/2bSX8RTpHPgDffMz7++rN2M+T5ZUEr 7I2ViQOxfo8bfv/0QuM6EsitPCiLYbCP1woFH/stfHZ+anEQloUKOhEb70MMZT/8gAO8 NTiauOGpmgvdgOJirO8AUKnz7g75a60HygFAoWsMookCotKtaB1ULNPLgZ6+BM1QfXLw IVWjbqAl7fIJHsLVmSEnDn1BvH9xdlL74bXp2q4EGHJhI7GVTMcHG8rI0kR3aZPlE7S6 rmpJUrwzXnBXqWg1GjeEDCiXmmKv3NrzzocOWiADbIP4Vf8CffnrryE7fRoU3h7xJKhC J76w== X-Gm-Message-State: AA+aEWZu8zbjSOlsV735IjAq1wI6ndqTx6k+zPWVKyf+Hz3x3veKArxM TRLOfhgsZhSF1zYX7QBooOlRoV6CiMrMxdn2KXtb7w== X-Google-Smtp-Source: AFSGD/X607UH9JitvEqYTY5c82SVaWcL1afuLN112Pho2wWdWhA+ulE1W03M43FlT4mFMPOFteQKW+7axRKEqm9MPCY= X-Received: by 2002:a19:c70a:: with SMTP id x10mr20372246lff.88.1546395834915; Tue, 01 Jan 2019 18:23:54 -0800 (PST) MIME-Version: 1.0 References: <8753521a-4555-ec2a-5efc-dee2660b4d9b@digiware.nl> <969d9a38-d3dd-78d0-c974-ba14ec4747db@digiware.nl> In-Reply-To: <969d9a38-d3dd-78d0-c974-ba14ec4747db@digiware.nl> From: Alan Somers Date: Tue, 1 Jan 2019 19:23:43 -0700 Message-ID: Subject: Re: Using kqueue with aio_read/write To: Willem Jan Withagen Cc: FreeBSD Hackers Content-Type: text/plain; charset="UTF-8" X-Rspamd-Queue-Id: 646516DDBD X-Spamd-Bar: ------ Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-6.96 / 15.00]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.96)[-0.956,0]; REPLY(-4.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000,0] X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Jan 2019 02:24:03 -0000 On Tue, Jan 1, 2019 at 6:56 PM Willem Jan Withagen wrote: > > On 28/12/2018 02:47, Alan Somers wrote: > > On Thu, Dec 27, 2018 at 6:15 PM Willem Jan Withagen 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 > >> #include > >> #include > >> #include > >> #include > >> #include > >> #include > >> #include > >> #include > >> > >> #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