Re: Panic on kern_event.c

From: Mark Johnston <markj_at_freebsd.org>
Date: Tue, 20 Nov 2018 01:45:00 -0500
On Mon, Nov 19, 2018 at 10:26:51AM +0100, Sylvain GALLIANO wrote:
> With this latest patch, after stressing syslog-ng few minutes, it do not
> log anymore and a simple kill do not work (I have to do kill -9)

Thanks for your patience.  I finally managed to reproduce the problem
and can see the bug now.  Please try this patch instead.

diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index d9c670e29d60..0be765a040ed 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
_at__at_ -1538,6 +1538,10 _at__at_ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
 			kn_enter_flux(kn);
 
 			error = knote_attach(kn, kq);
+			if ((kev->flags & EV_ENABLE) != 0)
+				kn->kn_status &= ~KN_DISABLED;
+			else if ((kev->flags & EV_DISABLE) != 0)
+				kn->kn_status |= KN_DISABLED;
 			KQ_UNLOCK(kq);
 			if (error != 0) {
 				tkn = kn;
_at__at_ -1570,6 +1574,11 _at__at_ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
 		KNOTE_ACTIVATE(kn, 1);
 	}
 
+	if ((kev->flags & EV_ENABLE) != 0)
+		kn->kn_status &= ~KN_DISABLED;
+	else if ((kev->flags & EV_DISABLE) != 0)
+		kn->kn_status |= KN_DISABLED;
+
 	/*
 	 * The user may change some filter values after the initial EV_ADD,
 	 * but doing so will not reset any filter which has already been
_at__at_ -1595,11 +1604,9 _at__at_ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
 	 * kn_knlist.
 	 */
 done_ev_add:
-	if ((kev->flags & EV_ENABLE) != 0)
-		kn->kn_status &= ~KN_DISABLED;
-	else if ((kev->flags & EV_DISABLE) != 0)
-		kn->kn_status |= KN_DISABLED;
-
+	/*
+	 * KN_DISABLED will be stable while the knote is in flux.
+	 */
 	if ((kn->kn_status & KN_DISABLED) == 0)
 		event = kn->kn_fop->f_event(kn, 0);
 	else
_at__at_ -1861,6 +1868,8 _at__at_ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent_copyops *k_ops,
 		}
 
 		TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
+		KASSERT(kn == marker || (kn->kn_status & KN_QUEUED) != 0,
+		    ("knote %p not queued", kn));
 		if ((kn->kn_status & KN_DISABLED) == KN_DISABLED) {
 			kn->kn_status &= ~KN_QUEUED;
 			kq->kq_count--;
Received on Tue Nov 20 2018 - 05:45:06 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:41:19 UTC