When registering a new kevent backed by a file descriptor, we first look
up the file description with fget(), then lock the kqueue, then see if a
corresponding knote is already registered. If not, and KN_ADD is
specified, we add the knote to the kqueue.
closefp_impl() interlocks with this process by calling knote_fdclose(),
which locks each kqueue and checks to see if the fd is registered with a
knote. But, if userspace closes an fd while a different thread is
registering it, i.e., after fget() succeeds but before the kqueue is
locked, then we may end up with a mismatch in the knote table, where the
knote kn_fp field points to a different file description than the knote
ident.
Fix the problem by double-checking before registering a knote. Add a
new fget_noref_unlocked() helper for this purpose. It is a clone of
fget_noref(). We could simply use fget_noref(), but I like having an
explicit unlocked variant.
PR: 293382