-/* $OpenBSD: kern_event.c,v 1.37 2010/07/28 21:44:41 nicm Exp $ */
+/* $OpenBSD: kern_event.c,v 1.38 2010/08/02 19:54:07 guenther Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
if (p == NULL)
return (ESRCH);
+ /* threads and exiting processes can't be specified */
+ if (p->p_flag & (P_THREAD|P_WEXIT))
+ return (ESRCH);
+
/*
* Fail if it's not owned by you, or the last exec gave us
* setuid/setgid privs (unless you're root).
kn->kn_fflags |= event;
/*
- * process is gone, so flag the event as finished.
+ * process is gone, so flag the event as finished and remove it
+ * from the process's klist
*/
if (event == NOTE_EXIT) {
+ struct process *pr = kn->kn_ptr.p_proc->p_p;
+
kn->kn_status |= KN_DETACHED;
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
+ SLIST_REMOVE(&pr->ps_klist, kn, knote, kn_selnext);
return (1);
}
knote_remove(p, list);
}
+/*
+ * handle a process exiting, including the triggering of NOTE_EXIT notes
+ * XXX this could be more efficient, doing a single pass down the klist
+ */
+void
+knote_processexit(struct process *pr)
+{
+ KNOTE(&pr->ps_klist, NOTE_EXIT);
+
+ /* remove other knotes hanging off the process */
+ knote_remove(pr->ps_mainproc, &pr->ps_klist);
+}
+
void
knote_attach(struct knote *kn, struct filedesc *fdp)
{
-/* $OpenBSD: kern_exit.c,v 1.96 2010/07/26 01:56:27 guenther Exp $ */
+/* $OpenBSD: kern_exit.c,v 1.97 2010/08/02 19:54:07 guenther Exp $ */
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
/*
p->p_pctcpu = 0;
if ((p->p_flag & P_THREAD) == 0) {
- /* notify interested parties of our demise */
- KNOTE(&pr->ps_klist, NOTE_EXIT);
+ /* notify interested parties of our demise and clean up */
+ knote_processexit(pr);
/*
* Notify parent that we're gone. If we have P_NOZOMBIE
-/* $OpenBSD: event.h,v 1.14 2010/07/28 21:44:41 nicm Exp $ */
+/* $OpenBSD: event.h,v 1.15 2010/08/02 19:54:07 guenther Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
extern void knote(struct klist *list, long hint);
extern void knote_remove(struct proc *p, struct klist *list);
extern void knote_fdclose(struct proc *p, int fd);
+extern void knote_processexit(struct process *);
extern int kqueue_register(struct kqueue *kq,
struct kevent *kev, struct proc *p);
extern int filt_seltrue(struct knote *kn, long hint);