Re: Panic: "knote ... was already on knlist..." after main-n284826-d9d7b5948649

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Thu, 02 Apr 2026 13:01:42 UTC
On Thu, Apr 02, 2026 at 05:50:40AM -0700, David Wolfskill wrote:
> Build machine (kernel GENERIC) did not experience this.  So far, 3 out
> of 3 laptops have (the 4th one has yet to finish the build).
> 
> I snapped a photo, which is up at
> https://www.catwhisker.org/~david/FreeBSD/head/n284826/screen.jpg
> 
> The panic occurs during the late(r) part of the transition to multi-user
> mode.  I am happy to poke at one of the machines, given suitable clues:
> I tend to break stuff.
> 
> The machines had previously built and run main-n284804-f3b59bf28504.
> All machines are amd64, and I use PORTS_MODULES in /etc/src.conf to
> ensure that ports-resident kernel modules get rebuilt whenever the
> kernel does./~david/FreeBSD/head/n284826/screen.jpg
> 
> The panic occurs during the late(r) part of the transition to multi-user
> mode.  I am happy to poke at one of the machines, given suitable clues:
> I tend to break stuff.
> 
> A quick scan down the backtrace shows:
> db_trace_self_wrapper()
> vpanic()
> panic()
> knlist_remove()
> kqueue_fork_copy_list()
> kqueue_fork()
> fdcopy()
> do_fork()
> fork()
> sys_fork()
> amd64_syscall()
> fast_syscall_common()
> --- syscall
> KDB: enter: panic
> [ thread pid 1891 tld 100578 ]
> Stopped at	xffffffffff88c177c3 = kdb_enter+0x33:	movq	$0,0x15f7842(%rip)
> db> 

Peter Holm already reported this or similar issue.  Try this please.

commit 5da1dcf8b88ffa3591a84405a8ab29ebd846f2e0
Author: Konstantin Belousov <kib@FreeBSD.org>
Date:   Thu Apr 2 14:02:14 2026 +0300

    kqueue_fork_copy_knote(): zero kn_knlist for the copy before calling knlist_add()
    
    Reported by:    pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week

diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index dc9e8b71ea13..5b0a3e59b715 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -3103,6 +3103,7 @@ kqueue_fork_copy_knote(struct kqueue *kq1, struct knote *kn, struct proc *p1,
 	kn1->kn_status |= KN_DETACHED;
 	kn1->kn_status &= ~KN_QUEUED;
 	kn1->kn_kq = kq1;
+	kn1->kn_knlist = NULL;
 	error = fop->f_copy(kn1, p1);
 	if (error != 0) {
 		knote_free(kn1);