svn commit: r264231 - in head: lib/libc/sys sys/kern sys/sys

Ed Schouten ed at FreeBSD.org
Mon Apr 7 18:10:51 UTC 2014


Author: ed
Date: Mon Apr  7 18:10:49 2014
New Revision: 264231
URL: http://svnweb.freebsd.org/changeset/base/264231

Log:
  Implement kqueue(2) for procdesc(4).
  
  kqueue(2) already supports EVFILT_PROC. Add an EVFILT_PROCDESC that
  behaves the same, but operates on a procdesc(4) instead. Only implement
  NOTE_EXIT for now. The nice thing about NOTE_EXIT is that it also
  returns the exit status of the process, meaning that we can now obtain
  this value, even if pdwait4(2) is still unimplemented.
  
  Notes:
  
  - Simply reuse EVFILT_NETDEV for EVFILT_PROCDESC. As both of these will
    be used on totally different descriptor types, this should not clash.
  
  - Let procdesc_kqops_event() reuse the same structure as filt_proc().
    The only difference is that procdesc_kqops_event() should also be able
    to deal with the case where the process was already terminated after
    registration. Simply test this when hint == 0.
  
  - Fix some style(9) issues in filt_proc() to keep it consistent with the
    newly added procdesc_kqops_event().
  
  - Save the exit status of the process in pd->pd_xstat, as we cannot pick
    up the proctree_lock from within procdesc_kqops_event().
  
  Discussed on:	arch@
  Reviewed by:	kib@

Modified:
  head/lib/libc/sys/kqueue.2
  head/lib/libc/sys/pdfork.2
  head/sys/kern/kern_event.c
  head/sys/kern/sys_procdesc.c
  head/sys/sys/event.h
  head/sys/sys/procdesc.h

Modified: head/lib/libc/sys/kqueue.2
==============================================================================
--- head/lib/libc/sys/kqueue.2	Mon Apr  7 16:38:31 2014	(r264230)
+++ head/lib/libc/sys/kqueue.2	Mon Apr  7 18:10:49 2014	(r264231)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 4, 2013
+.Dd April 7, 2014
 .Dt KQUEUE 2
 .Os
 .Sh NAME
@@ -412,6 +412,24 @@ and the child process will not signal a 
 On return,
 .Va fflags
 contains the events which triggered the filter.
+.It EVFILT_PROCDESC
+Takes the process descriptor created by
+.Xr pdfork 2
+to monitor as the identifier and the events to watch for in
+.Va fflags ,
+and returns when the associated process performs one or more of the
+requested events.
+The events to monitor are:
+.Bl -tag -width XXNOTE_EXIT
+.It NOTE_EXIT
+The process has exited.
+The exit status will be stored in
+.Va data .
+.El
+.Pp
+On return,
+.Va fflags
+contains the events which triggered the filter.
 .It EVFILT_SIGNAL
 Takes the signal number to monitor as the identifier and returns
 when the given signal is delivered to the process.

Modified: head/lib/libc/sys/pdfork.2
==============================================================================
--- head/lib/libc/sys/pdfork.2	Mon Apr  7 16:38:31 2014	(r264230)
+++ head/lib/libc/sys/pdfork.2	Mon Apr  7 18:10:49 2014	(r264231)
@@ -32,7 +32,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 4, 2014
+.Dd April 7, 2014
 .Dt PDFORK 2
 .Os
 .Sh NAME
@@ -117,6 +117,13 @@ and
 allow waiting for process state transitions; currently only
 .Dv POLLHUP
 is defined, and will be raised when the process dies.
+Process state transitions can also be monitored using
+.Xr kqueue 2
+filter
+.Dv EVFILT_PROCDESC ;
+currently only
+.Dv NOTE_EXIT
+is implemented.
 .Pp
 .Xr close 2
 will close the process descriptor unless

Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c	Mon Apr  7 16:38:31 2014	(r264230)
+++ head/sys/kern/kern_event.c	Mon Apr  7 18:10:49 2014	(r264231)
@@ -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;

Modified: head/sys/kern/sys_procdesc.c
==============================================================================
--- head/sys/kern/sys_procdesc.c	Mon Apr  7 16:38:31 2014	(r264230)
+++ head/sys/kern/sys_procdesc.c	Mon Apr  7 18:10:49 2014	(r264231)
@@ -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 event
 	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

Modified: head/sys/sys/event.h
==============================================================================
--- head/sys/sys/event.h	Mon Apr  7 16:38:31 2014	(r264230)
+++ head/sys/sys/event.h	Mon Apr  7 18:10:49 2014	(r264231)
@@ -38,7 +38,7 @@
 #define EVFILT_PROC		(-5)	/* attached to struct proc */
 #define EVFILT_SIGNAL		(-6)	/* attached to struct proc */
 #define EVFILT_TIMER		(-7)	/* timers */
-/*	EVFILT_NETDEV		(-8)	   no longer supported */
+#define EVFILT_PROCDESC		(-8)	/* attached to process descriptors */
 #define EVFILT_FS		(-9)	/* filesystem events */
 #define EVFILT_LIO		(-10)	/* attached to lio requests */
 #define EVFILT_USER		(-11)	/* User events */
@@ -120,7 +120,7 @@ struct kevent {
 #define	NOTE_REVOKE	0x0040			/* vnode access was revoked */
 
 /*
- * data/hint flags for EVFILT_PROC, shared with userspace
+ * data/hint flags for EVFILT_PROC and EVFILT_PROCDESC, shared with userspace
  */
 #define	NOTE_EXIT	0x80000000		/* process exited */
 #define	NOTE_FORK	0x40000000		/* process forked */

Modified: head/sys/sys/procdesc.h
==============================================================================
--- head/sys/sys/procdesc.h	Mon Apr  7 16:38:31 2014	(r264230)
+++ head/sys/sys/procdesc.h	Mon Apr  7 18:10:49 2014	(r264231)
@@ -68,6 +68,7 @@ struct procdesc {
 	 * In-flight data and notification of events.
 	 */
 	int		 pd_flags;		/* (p) PD_ flags. */
+	u_short		 pd_xstat;		/* (p) Exit status. */
 	struct selinfo	 pd_selinfo;		/* (p) Event notification. */
 	struct mtx	 pd_lock;		/* Protect data + events. */
 };


More information about the svn-src-head mailing list