--- sys/sys/procdesc.h 2012-11-27 12:15:40.872728289 +0100 +++ sys/sys/procdesc.h 2012-11-27 12:14:43.956385574 +0100 @@ -87,6 +87,7 @@ #define PDF_SELECTED 0x00000002 /* Issue selwakeup(). */ #define PDF_EXITED 0x00000004 /* Process exited. */ #define PDF_DAEMON 0x00000008 /* Don't exit when procdesc closes. */ +#define PDF_KNOTE 0x00000010 /* Issue KNOTE_LOCKED(). */ /* * In-kernel interfaces to process descriptors. --- sys/kern/sys_procdesc.c 2012-11-16 10:06:49.712336836 +0100 +++ sys/kern/sys_procdesc.c 2012-11-27 12:12:55.879727484 +0100 @@ -116,6 +116,16 @@ .fo_flags = DFLAG_PASSABLE, }; +static int procdesc_kqread(struct knote *note, long hint); +static void procdesc_kqdetach(struct knote *note); + +static struct filterops procdesc_filterops = { + .f_isfd = 1, + .f_attach = NULL, + .f_detach = procdesc_kqdetach, + .f_event = procdesc_kqread, +}; + /* * Initialize with VFS so that process descriptors are available along with * other file descriptor types. As long as it runs before init(8) starts, @@ -237,6 +247,7 @@ if (flags & PD_DAEMON) pd->pd_flags |= PDF_DAEMON; PROCDESC_LOCK_INIT(pd); + knlist_init_mtx(&pd->pd_selinfo.si_note, &pd->pd_lock); /* * Process descriptors start out with two references: one from their @@ -311,6 +322,10 @@ procdesc_free(pd); return (1); } + if (pd->pd_flags & PDF_KNOTE) { + pd->pd_flags &= ~PDF_KNOTE; + KNOTE_LOCKED(&pd->pd_selinfo.si_note, 0); + } if (pd->pd_flags & PDF_SELECTED) { pd->pd_flags &= ~PDF_SELECTED; selwakeup(&pd->pd_selinfo); @@ -462,8 +477,48 @@ static int procdesc_kqfilter(struct file *fp, struct knote *kn) { + struct procdesc *pd; - return (EOPNOTSUPP); + if (kn->kn_filter != EVFILT_READ) + return (EINVAL); + + kn->kn_fop = &procdesc_filterops; + kn->kn_hook = NULL; + + pd = fp->f_data; + PROCDESC_LOCK(pd); + knlist_add(&pd->pd_selinfo.si_note, kn, 1); + pd->pd_flags |= PDF_KNOTE; + PROCDESC_UNLOCK(pd); + return (0); +} + +static void +procdesc_kqdetach(struct knote *kn) +{ + struct procdesc *pd; + + pd = kn->kn_fp->f_data; + PROCDESC_LOCK(pd); + knlist_remove(&pd->pd_selinfo.si_note, kn, 1); + if (knlist_empty(&pd->pd_selinfo.si_note)) + pd->pd_flags &= ~PDF_KNOTE; + PROCDESC_UNLOCK(pd); +} + +static int +procdesc_kqread(struct knote *kn, long hint) +{ + struct procdesc *pd; + + pd = kn->kn_fp->f_data; + mtx_assert(&pd->pd_lock, MA_OWNED); + + if (pd->pd_flags & PDF_EXITED) { + kn->kn_flags |= EV_EOF; + return (1); + } + return (0); } static int