From owner-freebsd-hackers@FreeBSD.ORG Fri Mar 14 16:02:03 2008 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6F870106566B for ; Fri, 14 Mar 2008 16:02:03 +0000 (UTC) (envelope-from dan@dan.emsphone.com) Received: from dan.emsphone.com (dan.emsphone.com [199.67.51.101]) by mx1.freebsd.org (Postfix) with ESMTP id 3E03D8FC2C for ; Fri, 14 Mar 2008 16:02:03 +0000 (UTC) (envelope-from dan@dan.emsphone.com) Received: (from dan@localhost) by dan.emsphone.com (8.14.2/8.14.2) id m2EFc14n048462; Fri, 14 Mar 2008 10:38:01 -0500 (CDT) (envelope-from dan) Date: Fri, 14 Mar 2008 10:38:01 -0500 From: Dan Nelson To: Vlad GALU Message-ID: <20080314153801.GB30116@dan.emsphone.com> References: <20080307223723.X42870@fledge.watson.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="DocE+STaALJfprDB" Content-Disposition: inline In-Reply-To: X-OS: FreeBSD 7.0-STABLE User-Agent: Mutt/1.5.17 (2007-11-01) Cc: freebsd-hackers@freebsd.org Subject: Re: A (perhaps silly) kqueue question X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Mar 2008 16:02:03 -0000 --DocE+STaALJfprDB Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In the last episode (Mar 14), Vlad GALU said: > On 3/14/08, Vlad GALU wrote: > > On 3/8/08, Vlad GALU wrote: > > > On 3/8/08, Robert Watson wrote: > > > > On Fri, 7 Mar 2008, Vlad GALU wrote: > > > > > I see an unusual symptom with one of our in-house > > > > > applications. The main I/O loop calls kevent(), which in turn > > > > > returns two events with EV_EOF error set, always for the same > > > > > descriptors (they're both socket descriptors). As the man > > > > > page is not pretty clear about it and I don't have my UNP > > > > > copy at hand, I would like to ask the list whether the error > > > > > events are supposed to be one-shot or not. > > > > > > > > I wonder if it's returning one event for the read socket > > > > buffer, and one event for the write socket buffer, since there > > > > are really two event sources for each socket? Not that this > > > > is desirable behavior, but it might explain it. If you > > > > shutdown() only read, do you get back one EOF kevent and one > > > > writable kevent? > > > > > > I'll try that and see. The only issue being the low frequency > > > this symptom appears at. I'll get back to the list once I have > > > more info. > > > > Haven't gotten to the point of testing shutdown() behavior, but > > here's a truss excerpt of the symptom: > > > > -- cut here -- > > kevent(3,0x0,0,{0x7,EVFILT_WRITE,EV_EOF,54,0x832c,0x800d08080 0x7,EVFILT_READ,EV_EOF,54,0x2a,0x800d08080},1024,0x0) = 2 (0x2) > > kevent(3,0x0,0,{0x7,EVFILT_WRITE,EV_EOF,54,0x832c,0x800d08080 0x7,EVFILT_READ,EV_EOF,54,0x2a,0x800d08080},1024,0x0) = 2 (0x2) > > kevent(3,0x0,0,{0x7,EVFILT_WRITE,EV_EOF,54,0x832c,0x800d08080 0x7,EVFILT_READ,EV_EOF,54,0x2a,0x800d08080},1024,0x0) = 2 (0x2) > > -- and here -- > > > > So two EOF are returrned for descriptor 7, and errno would be > > ECONNRESET. The question is now, why isn't it oneshot? > > Ah one more thing. When EOF is caught, a handler which forcibly > removes the event is called, but it keeps poping up again and again. Are you sure the event is being removed? I used to have a hack that made the kernel return its current eventlist for a kqueue when you called kevent() with nchanges set to -1 (handy for placing in a program and using truss to print the result), but it has rotted. I'm attaching it in case anyone wants to make it work again. Since you got EOF status for both the read and write halves of the socket, why not just close the fd? From my reading of the manpages, unless you specified EV_ONESHOT when you added the event, events will fire until you remove them or the condition that triggers them stops. -- Dan Nelson dnelson@allantgroup.com --DocE+STaALJfprDB Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="kern_kevent.c.diff" Index: kern_event.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_event.c,v retrieving revision 1.113 diff -u -r1.113 kern_event.c --- kern_event.c 14 Jul 2007 21:23:30 -0000 1.113 +++ kern_event.c 17 Jul 2007 18:10:47 -0000 @@ -659,6 +659,41 @@ nerrors = 0; +#if 0 /* 1.92 broke this */ + if (nchanges == -1) { + /* dump our eventlist into k_ops->arg */ + int i; + int count = 0; + struct knote *kn; + error = 0; + KQ_LOCK(kq); + + /* Walk our filedescriptor lists */ + for (i = 0; i < kq->kq_knlistsize && count < nevents; i++) { + SLIST_FOREACH(kn, &kq->kq_knlist[i], kn_link) { + copyout(&kn->kn_kevent, &(struct kevent)k_ops->arg[count], sizeof(kn->kn_kevent)); + count++; + if (count >= nevents) + break; + } + } + + /* Walk our hash tables */ + if (kq->kq_knhashmask != 0) { + for (i = 0; i <= kq->kq_knhashmask && count < nevents; i++) { + SLIST_FOREACH(kn, &kq->kq_knhash[i], kn_link) { + copyout(&kn->kn_kevent, &(struct kevent)k_ops->arg[count], sizeof(kn->kn_kevent)); + count++; + if (count >= nevents) + break; + } + } + } + KQ_UNLOCK(kq); + td->td_retval[0] = count; + goto done; + } +#endif while (nchanges > 0) { n = nchanges > KQ_NEVENTS ? KQ_NEVENTS : nchanges; error = k_ops->k_copyin(k_ops->arg, keva, n); @@ -961,10 +996,12 @@ if ((kev->flags & EV_DISABLE) && ((kn->kn_status & KN_DISABLED) == 0)) { kn->kn_status |= KN_DISABLED; + kn->kn_kevent.flags |= EV_DISABLE; } if ((kev->flags & EV_ENABLE) && (kn->kn_status & KN_DISABLED)) { kn->kn_status &= ~KN_DISABLED; + kn->kn_kevent.flags &= ~EV_DISABLE; if ((kn->kn_status & KN_ACTIVE) && ((kn->kn_status & KN_QUEUED) == 0)) knote_enqueue(kn); --DocE+STaALJfprDB--