Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 05 Oct 2002 12:12:59 -0700
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Stefan Farfeleder <e0026813@stud3.tuwien.ac.at>
Cc:        John Baldwin <jhb@FreeBSD.org>, Juli Mallett <jmallett@FreeBSD.org>, current@FreeBSD.org
Subject:   [PATCH] Re: Junior Kernel Hacker page updated...
Message-ID:  <3D9F39BB.66126C35@mindspring.com>
References:  <20021004132203.A78223@FreeBSD.org> <XFMail.20021004163317.jhb@FreeBSD.org> <20021005135504.GA254@frog.fafoe>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------6432A5E3A2499CE19F1AEDE9
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Stefan Farfeleder wrote:
> (kgdb) l *kqueue_scan+0x242
> 0xc01a1212 is in kqueue_scan
> (/freebsd/current/src/sys/kern/kern_event.c:716).
> 713             TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe);
> 714             while (count) {
> 715                     kn = TAILQ_FIRST(&kq->kq_head);
> translates to:          mov    (%edi),%ebx
> 716                     TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
> translates to:          cmpl   $0x0,0x8(%ebx)
> 
> This line causes the page fault because %ebx is 0.


This can't happen, at least from an "empty list" perspective,
even if kqueue_scan() is reentered, since the "marker" is an
auto allocation on the stack, and a different stack means a
different marker gets inserted (marker isn't static, so having
more than one insert of the marker won't result in only a
single insertion).

I suspect that what is hapening is that the code is being
reentered, and one marker is being treated as an event, because
of whatever garbage happens to be on the stack in the allocated
marker.

The marker is removed, and then it is not found before you hit
the end of the list.

Please try the attached patch.

-- Terry
--------------6432A5E3A2499CE19F1AEDE9
Content-Type: text/plain; charset=us-ascii;
 name="kpanic.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="kpanic.diff"

Index: sys/event.h
===================================================================
RCS file: /cvs/src/sys/sys/event.h,v
retrieving revision 1.21
diff -c -r1.21 event.h
*** sys/event.h	29 Jun 2002 19:14:52 -0000	1.21
--- sys/event.h	5 Oct 2002 15:12:24 -0000
***************
*** 160,165 ****
--- 160,166 ----
  #define KN_QUEUED	0x02			/* event is on queue */
  #define KN_DISABLED	0x04			/* event is disabled */
  #define KN_DETACHED	0x08			/* knote is detached */
+ #define KN_MARKER	0x10			/* knote is a scan marker */
  
  #define kn_id		kn_kevent.ident
  #define kn_filter	kn_kevent.filter
Index: kern/kern_event.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.45
diff -c -r1.45 kern_event.c
*** kern/kern_event.c	17 Aug 2002 02:36:16 -0000	1.45
--- kern/kern_event.c	5 Oct 2002 15:13:26 -0000
***************
*** 653,658 ****
--- 653,659 ----
  
  	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
  
+ 	marker.kn_status = KN_MARKER;
  	kq = (struct kqueue *)fp->f_data;
  	count = maxevents;
  	if (count == 0)
***************
*** 713,718 ****
--- 714,727 ----
  	TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe); 
  	while (count) {
  		kn = TAILQ_FIRST(&kq->kq_head);
+ 		/*
+ 		 * Skip over all markers which are not ours.  This looks
+ 		 * unsafe, but we can't hit the end of the list without
+ 		 * hitting our own marker.
+ 		 */
+ 		while ((kn->kn_status & KN_MARKER) && (kn != &marker)) {
+ 			kn = TAILQ_NEXT(kn, kn_tqe);
+ 		}
  		TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); 
  		if (kn == &marker) {
  			splx(s);

--------------6432A5E3A2499CE19F1AEDE9--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3D9F39BB.66126C35>