diff options
| author | Ed Schouten <ed@FreeBSD.org> | 2014-04-07 18:10:49 +0000 |
|---|---|---|
| committer | Ed Schouten <ed@FreeBSD.org> | 2014-04-07 18:10:49 +0000 |
| commit | 38219d6acdfd2a273e4a08b278aea6cdb3e4945e (patch) | |
| tree | 86add6f815ce421c32d599a69a835b29dee9b881 /sys/kern | |
| parent | 29aa8ff1dd2f68f62c866c8f64748406ddb38bae (diff) | |
Notes
Diffstat (limited to 'sys/kern')
| -rw-r--r-- | sys/kern/kern_event.c | 19 | ||||
| -rw-r--r-- | sys/kern/sys_procdesc.c | 66 |
2 files changed, 72 insertions, 13 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index fadb8fd1ad2e6..9b095b0bf158c 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -290,7 +290,7 @@ static struct { { &proc_filtops }, /* EVFILT_PROC */ { &sig_filtops }, /* EVFILT_SIGNAL */ { &timer_filtops }, /* EVFILT_TIMER */ - { &null_filtops }, /* former EVFILT_NETDEV */ + { &file_filtops }, /* EVFILT_PROCDESC */ { &fs_filtops }, /* EVFILT_FS */ { &null_filtops }, /* EVFILT_LIO */ { &user_filtops }, /* EVFILT_USER */ @@ -417,27 +417,22 @@ filt_procdetach(struct knote *kn) static int filt_proc(struct knote *kn, long hint) { - struct proc *p = kn->kn_ptr.p_proc; + struct proc *p; u_int event; - /* - * mask off extra data - */ + p = kn->kn_ptr.p_proc; + /* Mask off extra data. */ event = (u_int)hint & NOTE_PCTRLMASK; - /* - * if the user is interested in this event, record it. - */ + /* If the user is interested in this event, record it. */ if (kn->kn_sfflags & event) kn->kn_fflags |= event; - /* - * process is gone, so flag the event as finished. - */ + /* Process is gone, so flag the event as finished. */ if (event == NOTE_EXIT) { if (!(kn->kn_status & KN_DETACHED)) knlist_remove_inevent(&p->p_klist, kn); - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= EV_EOF | EV_ONESHOT; kn->kn_ptr.p_proc = NULL; if (kn->kn_fflags & NOTE_EXIT) kn->kn_data = p->p_xstat; diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c index 0c2743f47c7c9..1039dac6e2a8e 100644 --- a/sys/kern/sys_procdesc.c +++ b/sys/kern/sys_procdesc.c @@ -236,6 +236,7 @@ procdesc_new(struct proc *p, int flags) 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 @@ -270,6 +271,7 @@ procdesc_free(struct procdesc *pd) KASSERT((pd->pd_flags & PDF_CLOSED), ("procdesc_free: !PDF_CLOSED")); + knlist_destroy(&pd->pd_selinfo.si_note); PROCDESC_LOCK_DESTROY(pd); uma_zfree(procdesc_zone, pd); } @@ -296,6 +298,7 @@ procdesc_exit(struct proc *p) ("procdesc_exit: closed && parent not init")); pd->pd_flags |= PDF_EXITED; + pd->pd_xstat = p->p_xstat; /* * If the process descriptor has been closed, then we have nothing @@ -314,6 +317,7 @@ procdesc_exit(struct proc *p) pd->pd_flags &= ~PDF_SELECTED; selwakeup(&pd->pd_selinfo); } + KNOTE_LOCKED(&pd->pd_selinfo.si_note, NOTE_EXIT); PROCDESC_UNLOCK(pd); return (0); } @@ -460,11 +464,71 @@ procdesc_poll(struct file *fp, int events, struct ucred *active_cred, return (revents); } +static void +procdesc_kqops_detach(struct knote *kn) +{ + struct procdesc *pd; + + pd = kn->kn_fp->f_data; + knlist_remove(&pd->pd_selinfo.si_note, kn, 0); +} + +static int +procdesc_kqops_event(struct knote *kn, long hint) +{ + struct procdesc *pd; + u_int event; + + pd = kn->kn_fp->f_data; + if (hint == 0) { + /* + * Initial test after registration. Generate a NOTE_EXIT in + * case the process already terminated before registration. + */ + event = pd->pd_flags & PDF_EXITED ? NOTE_EXIT : 0; + } else { + /* Mask off extra data. */ + event = (u_int)hint & NOTE_PCTRLMASK; + } + + /* If the user is interested in this event, record it. */ + if (kn->kn_sfflags & event) + kn->kn_fflags |= event; + + /* Process is gone, so flag the event as finished. */ + if (event == NOTE_EXIT) { + kn->kn_flags |= EV_EOF | EV_ONESHOT; + if (kn->kn_fflags & NOTE_EXIT) + kn->kn_data = pd->pd_xstat; + if (kn->kn_fflags == 0) + kn->kn_flags |= EV_DROP; + return (1); + } + + return (kn->kn_fflags != 0); +} + +static struct filterops procdesc_kqops = { + .f_isfd = 1, + .f_detach = procdesc_kqops_detach, + .f_event = procdesc_kqops_event, +}; + static int procdesc_kqfilter(struct file *fp, struct knote *kn) { + struct procdesc *pd; - return (EOPNOTSUPP); + pd = fp->f_data; + switch (kn->kn_filter) { + case EVFILT_PROCDESC: + kn->kn_fop = &procdesc_kqops; + kn->kn_flags |= EV_CLEAR; + knlist_add(&pd->pd_selinfo.si_note, kn, 0); + return (0); + default: + return (EINVAL); + } } static int |
