Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Mar 2008 10:38:01 -0500
From:      Dan Nelson <dnelson@allantgroup.com>
To:        Vlad GALU <dudu@dudu.ro>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: A (perhaps silly) kqueue question
Message-ID:  <20080314153801.GB30116@dan.emsphone.com>
In-Reply-To: <ad79ad6b0803140553j2b509e8alf17696f268eeb350@mail.gmail.com>
References:  <ad79ad6b0803070847v7464381en958ef73455ed9c89@mail.gmail.com> <20080307223723.X42870@fledge.watson.org> <ad79ad6b0803080009w45fc866euf43ea7e9dbf6b5f5@mail.gmail.com> <ad79ad6b0803140530td3376b8v9307628ed147a89d@mail.gmail.com> <ad79ad6b0803140553j2b509e8alf17696f268eeb350@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--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 <dudu@dudu.ro> wrote:
> > On 3/8/08, Vlad GALU <dudu@dudu.ro> wrote:
> > > On 3/8/08, Robert Watson <rwatson@freebsd.org> 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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080314153801.GB30116>