Index: share/man/man9/Makefile =================================================================== --- share/man/man9/Makefile (revision 225142) +++ share/man/man9/Makefile (working copy) @@ -1075,7 +1075,7 @@ scheduler.9 setrunnable.9 \ scheduler.9 updatepri.9 MLINKS+=securelevel_gt.9 securelevel_ge.9 -MLINKS+=selrecord.9 selwakeup.9 +MLINKS+=seldrain.9 selrecord.9 selwakeup.9 MLINKS+=sema.9 sema_destroy.9 \ sema.9 sema_init.9 \ sema.9 sema_post.9 \ Index: share/man/man9/selrecord.9 =================================================================== --- share/man/man9/selrecord.9 (revision 225142) +++ share/man/man9/selrecord.9 (working copy) @@ -26,10 +26,11 @@ .\" .\" $FreeBSD$ .\" -.Dd June 13, 2007 +.Dd August 21, 2011 .Dt SELRECORD 9 .Os .Sh NAME +.Nm seldrain , .Nm selrecord , .Nm selwakeup .Nd "record and wakeup select requests" @@ -37,14 +38,17 @@ .In sys/param.h .In sys/selinfo.h .Ft void +.Fn seldrain "struct selinfo *sip" +.Ft void .Fn selrecord "struct thread *td" "struct selinfo *sip" .Ft void .Fn selwakeup "struct selinfo *sip" .Sh DESCRIPTION +.Fn seldrain , .Fn selrecord and .Fn selwakeup -are the two central functions used by +are the three central functions used by .Xr select 2 , .Xr poll 2 and the objects that are being selected on. @@ -86,6 +90,12 @@ .Xr poll 2 when they wake up. .Pp +.Fn seldrain +will flush the waiters queue on a specified object, before its actual +destruction. +The context should ensure no further object registering happens past +that point. +.Pp The contents of .Fa *sip must be zeroed, such as by softc initialization, before any call to @@ -98,6 +108,10 @@ .Va sellock and may acquire and release .Va sched_lock . +.Fn seldrain +could usually be just a wrapper for +.Fn selwakeup , +but consumers should not generally rely on this feature. .Sh SEE ALSO .Xr poll 2 , .Xr select 2 Index: sys/kern/uipc_mqueue.c =================================================================== --- sys/kern/uipc_mqueue.c (revision 225142) +++ sys/kern/uipc_mqueue.c (working copy) @@ -1562,6 +1562,8 @@ } mtx_destroy(&mq->mq_mutex); + seldrain(&mq->mq_rsel); + seldrain(&mq->mq_wsel); knlist_destroy(&mq->mq_rsel.si_note); knlist_destroy(&mq->mq_wsel.si_note); uma_zfree(mqueue_zone, mq); Index: sys/kern/tty_pts.c =================================================================== --- sys/kern/tty_pts.c (revision 225142) +++ sys/kern/tty_pts.c (working copy) @@ -688,6 +688,8 @@ racct_sub_cred(psc->pts_cred, RACCT_NPTS, 1); crfree(psc->pts_cred); + seldrain(&psc->pts_inpoll); + seldrain(&psc->pts_outpoll); knlist_destroy(&psc->pts_inpoll.si_note); knlist_destroy(&psc->pts_outpoll.si_note); Index: sys/kern/uipc_socket.c =================================================================== --- sys/kern/uipc_socket.c (revision 225142) +++ sys/kern/uipc_socket.c (working copy) @@ -661,6 +661,8 @@ */ sbdestroy(&so->so_snd, so); sbdestroy(&so->so_rcv, so); + seldrain(&so->so_snd.sb_sel); + seldrain(&so->so_rcv.sb_sel); knlist_destroy(&so->so_rcv.sb_sel.si_note); knlist_destroy(&so->so_snd.sb_sel.si_note); sodealloc(so); Index: sys/kern/tty.c =================================================================== --- sys/kern/tty.c (revision 225142) +++ sys/kern/tty.c (working copy) @@ -1022,6 +1022,8 @@ MPASS(ttyinq_getsize(&tp->t_inq) == 0); MPASS(ttyoutq_getsize(&tp->t_outq) == 0); + seldrain(&tp->t_inpoll); + seldrain(&tp->t_outpoll); knlist_destroy(&tp->t_inpoll.si_note); knlist_destroy(&tp->t_outpoll.si_note); Index: sys/kern/kern_event.c =================================================================== --- sys/kern/kern_event.c (revision 225142) +++ sys/kern/kern_event.c (working copy) @@ -1704,6 +1704,7 @@ SLIST_REMOVE(&fdp->fd_kqlist, kq, kqueue, kq_list); FILEDESC_XUNLOCK(fdp); + seldrain(&kq->kq_sel); knlist_destroy(&kq->kq_sel.si_note); mtx_destroy(&kq->kq_lock); kq->kq_fdp = NULL; Index: sys/kern/sys_generic.c =================================================================== --- sys/kern/sys_generic.c (revision 225142) +++ sys/kern/sys_generic.c (working copy) @@ -1490,6 +1490,23 @@ uma_zfree(selfd_zone, sfp); } +/* Drain the waiters tied to all the selfd belonging the specified selinfo. */ +void +seldrain(sip) + struct selinfo *sip; +{ + + /* + * This feature is already provided by doselwakeup(), thus it is + * enough to go for it. + * Eventually, the context, should take care to avoid races + * between thread calling select()/poll() and file descriptor + * detaching, but, again, the races are just the same as + * selwakeup(). + */ + doselwakeup(sip, -1); +} + /* * Record a select request. */ Index: sys/kern/sys_pipe.c =================================================================== --- sys/kern/sys_pipe.c (revision 225142) +++ sys/kern/sys_pipe.c (working copy) @@ -1515,6 +1515,7 @@ * PIPE_FINALIZED, that allows other end to free the * pipe_pair, only after the knotes are completely dismantled. */ + seldrain(&cpipe->pipe_sel); knlist_clear(&cpipe->pipe_sel.si_note, 1); cpipe->pipe_present = PIPE_FINALIZED; knlist_destroy(&cpipe->pipe_sel.si_note); Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c (revision 225142) +++ sys/kern/vfs_subr.c (working copy) @@ -3312,6 +3312,7 @@ static void destroy_vpollinfo(struct vpollinfo *vi) { + seldrain(&vi->vpi_selinfo); knlist_destroy(&vi->vpi_selinfo.si_note); mtx_destroy(&vi->vpi_lock); uma_zfree(vnodepoll_zone, vi); Index: sys/x86/acpica/acpi_apm.c =================================================================== --- sys/x86/acpica/acpi_apm.c (revision 225142) +++ sys/x86/acpica/acpi_apm.c (working copy) @@ -297,6 +297,7 @@ /* Remove this clone's data from the list and free it. */ ACPI_LOCK(acpi); STAILQ_REMOVE(&acpi_sc->apm_cdevs, clone, apm_clone_data, entries); + seldrain(&clone->sel_read); knlist_destroy(&clone->sel_read.si_note); ACPI_UNLOCK(acpi); free(clone, M_APMDEV); Index: sys/net/bpf.c =================================================================== --- sys/net/bpf.c (revision 225142) +++ sys/net/bpf.c (working copy) @@ -652,10 +652,10 @@ if (d->bd_bif) bpf_detachd(d); mtx_unlock(&bpf_mtx); - selwakeuppri(&d->bd_sel, PRINET); #ifdef MAC mac_bpfdesc_destroy(d); #endif /* MAC */ + seldrain(&d->bd_sel); knlist_destroy(&d->bd_sel.si_note); callout_drain(&d->bd_callout); bpf_freed(d); Index: sys/net/if_tap.c =================================================================== --- sys/net/if_tap.c (revision 225142) +++ sys/net/if_tap.c (working copy) @@ -214,6 +214,7 @@ KASSERT(!(tp->tap_flags & TAP_OPEN), ("%s flags is out of sync", ifp->if_xname)); + seldrain(&tp->tap_rsel); knlist_destroy(&tp->tap_rsel.si_note); destroy_dev(tp->tap_dev); ether_ifdetach(ifp); Index: sys/net/if_tun.c =================================================================== --- sys/net/if_tun.c (revision 225142) +++ sys/net/if_tun.c (working copy) @@ -259,6 +259,7 @@ if_detach(TUN2IFP(tp)); if_free(TUN2IFP(tp)); destroy_dev(dev); + seldrain(&tp->tun_rsel); knlist_destroy(&tp->tun_rsel.si_note); mtx_destroy(&tp->tun_mtx); cv_destroy(&tp->tun_cv); Index: sys/security/audit/audit_pipe.c =================================================================== --- sys/security/audit/audit_pipe.c (revision 225142) +++ sys/security/audit/audit_pipe.c (working copy) @@ -646,6 +646,7 @@ cv_destroy(&ap->ap_cv); AUDIT_PIPE_SX_LOCK_DESTROY(ap); AUDIT_PIPE_LOCK_DESTROY(ap); + seldrain(&ap->ap_selinfo); knlist_destroy(&ap->ap_selinfo.si_note); TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); free(ap, M_AUDIT_PIPE); Index: sys/sys/selinfo.h =================================================================== --- sys/sys/selinfo.h (revision 225142) +++ sys/sys/selinfo.h (working copy) @@ -51,6 +51,7 @@ #define SEL_WAITING(si) (!TAILQ_EMPTY(&(si)->si_tdlist)) #ifdef _KERNEL +void seldrain(struct selinfo *sip); void selrecord(struct thread *selector, struct selinfo *sip); void selwakeup(struct selinfo *sip); void selwakeuppri(struct selinfo *sip, int pri);