summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c71
1 files changed, 45 insertions, 26 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 3e15012..e03c09f 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -534,17 +534,18 @@ do_dup(fdp, old, new, retval, td)
* free sigio.
*/
void
-funsetown(sigio)
- struct sigio *sigio;
+funsetown(sigiop)
+ struct sigio **sigiop;
{
+ struct sigio *sigio;
SIGIO_LOCK();
+ sigio = *sigiop;
if (sigio == NULL) {
SIGIO_UNLOCK();
return;
}
*(sigio->sio_myref) = NULL;
- SIGIO_UNLOCK();
if ((sigio)->sio_pgid < 0) {
struct pgrp *pg = (sigio)->sio_pgrp;
PGRP_LOCK(pg);
@@ -558,11 +559,17 @@ funsetown(sigio)
sigio, sio_pgsigio);
PROC_UNLOCK(p);
}
+ SIGIO_UNLOCK();
crfree(sigio->sio_ucred);
FREE(sigio, M_SIGIO);
}
-/* Free a list of sigio structures. */
+/*
+ * Free a list of sigio structures.
+ * We only need to lock the SIGIO_LOCK because we have made ourselves
+ * inaccessable to callers of fsetown and therefore do not need to lock
+ * the proc or pgrp struct for the list manipulation.
+ */
void
funsetownlst(sigiolst)
struct sigiolst *sigiolst;
@@ -571,8 +578,6 @@ funsetownlst(sigiolst)
struct proc *p;
struct pgrp *pg;
- SIGIO_ASSERT(MA_OWNED);
-
sigio = SLIST_FIRST(sigiolst);
if (sigio == NULL)
return;
@@ -586,36 +591,40 @@ funsetownlst(sigiolst)
*/
if (sigio->sio_pgid < 0) {
pg = sigio->sio_pgrp;
- PGRP_LOCK_ASSERT(pg, MA_OWNED);
+ PGRP_LOCK_ASSERT(pg, MA_NOTOWNED);
} else /* if (sigio->sio_pgid > 0) */ {
p = sigio->sio_proc;
- PROC_LOCK_ASSERT(p, MA_OWNED);
+ PROC_LOCK_ASSERT(p, MA_NOTOWNED);
}
+ SIGIO_LOCK();
while ((sigio = SLIST_FIRST(sigiolst)) != NULL) {
*(sigio->sio_myref) = NULL;
if (pg != NULL) {
- KASSERT(sigio->sio_pgid < 0, ("Proc sigio in pgrp sigio list"));
- KASSERT(sigio->sio_pgrp == pg, ("Bogus pgrp in sigio list"));
- SLIST_REMOVE(&pg->pg_sigiolst, sigio, sigio, sio_pgsigio);
- PGRP_UNLOCK(pg);
- SIGIO_UNLOCK();
- crfree(sigio->sio_ucred);
- FREE(sigio, M_SIGIO);
- SIGIO_LOCK();
+ KASSERT(sigio->sio_pgid < 0,
+ ("Proc sigio in pgrp sigio list"));
+ KASSERT(sigio->sio_pgrp == pg,
+ ("Bogus pgrp in sigio list"));
PGRP_LOCK(pg);
+ SLIST_REMOVE(&pg->pg_sigiolst, sigio, sigio,
+ sio_pgsigio);
+ PGRP_UNLOCK(pg);
} else /* if (p != NULL) */ {
- KASSERT(sigio->sio_pgid > 0, ("Pgrp sigio in proc sigio list"));
- KASSERT(sigio->sio_proc == p, ("Bogus proc in sigio list"));
- SLIST_REMOVE(&p->p_sigiolst, sigio, sigio, sio_pgsigio);
- PROC_UNLOCK(p);
- SIGIO_UNLOCK();
- crfree(sigio->sio_ucred);
- FREE(sigio, M_SIGIO);
- SIGIO_LOCK();
+ KASSERT(sigio->sio_pgid > 0,
+ ("Pgrp sigio in proc sigio list"));
+ KASSERT(sigio->sio_proc == p,
+ ("Bogus proc in sigio list"));
PROC_LOCK(p);
+ SLIST_REMOVE(&p->p_sigiolst, sigio, sigio,
+ sio_pgsigio);
+ PROC_UNLOCK(p);
}
+ SIGIO_UNLOCK();
+ crfree(sigio->sio_ucred);
+ FREE(sigio, M_SIGIO);
+ SIGIO_LOCK();
}
+ SIGIO_UNLOCK();
}
/*
@@ -635,7 +644,7 @@ fsetown(pgid, sigiop)
int ret;
if (pgid == 0) {
- funsetown(*sigiop);
+ funsetown(sigiop);
return (0);
}
@@ -693,9 +702,19 @@ fsetown(pgid, sigiop)
proc = NULL;
}
- funsetown(*sigiop);
+ funsetown(sigiop);
if (pgid > 0) {
PROC_LOCK(proc);
+ /*
+ * since funsetownlst() is called without the proctree
+ * locked we need to check for P_WEXIT.
+ * XXX: is ESRCH correct?
+ */
+ if ((proc->p_flag & P_WEXIT) != 0) {
+ PROC_UNLOCK(proc);
+ ret = ESRCH;
+ goto fail;
+ }
SLIST_INSERT_HEAD(&proc->p_sigiolst, sigio, sio_pgsigio);
sigio->sio_proc = proc;
PROC_UNLOCK(proc);
OpenPOWER on IntegriCloud