if you have a program that uses kq (or libevent) to wait for bytes to read off an idle network interface via /dev/bpf and that interface goes away, the program doesnt get woken up. this is because the kq read filter in bpf only checks if there ares bytes available. because a detached interface never gets packets (how very zen), this condition never changes and the program will never know something happened.
this has the bpf filter check if the interface is detached too. with this change my test program wakes up, tries to read, and gets EIO. which is great. note that in the middle of this is the vdevgone machinery. when an interface is detached, bpfdetach gets called, which ends up calling vdevgone. vdevgone sort of swaps out bpf on the currently open vdev with some dead operations, part of which involves calling bpfclose() to try and clean up the existing state associated with the vdev. bpfclose tries to wake up any waiting listeners, which includes kq handlers. that's how the kernel goes from an interface being detached to the bpf kq filter being run. the bpf kq filter just has to check that the interface is still attached. ok? Index: bpf.c =================================================================== RCS file: /cvs/src/sys/net/bpf.c,v retrieving revision 1.203 diff -u -p -r1.203 bpf.c --- bpf.c 21 Jan 2021 12:33:14 -0000 1.203 +++ bpf.c 21 Apr 2021 00:03:15 -0000 @@ -1222,6 +1222,7 @@ int filt_bpfread(struct knote *kn, long hint) { struct bpf_d *d = kn->kn_hook; + struct bpf_if *bp; KERNEL_ASSERT_LOCKED(); @@ -1229,9 +1230,11 @@ filt_bpfread(struct knote *kn, long hint kn->kn_data = d->bd_hlen; if (d->bd_immediate) kn->kn_data += d->bd_slen; + + bp = d->bd_bif; /* check that the interface is still attached */ mtx_leave(&d->bd_mtx); - return (kn->kn_data > 0); + return (kn->kn_data > 0 || bp == NULL); } /*