summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c71
-rw-r--r--sys/kern/kern_exit.c4
-rw-r--r--sys/kern/kern_proc.c5
-rw-r--r--sys/kern/subr_log.c2
-rw-r--r--sys/kern/subr_witness.c1
-rw-r--r--sys/kern/sys_pipe.c2
-rw-r--r--sys/kern/tty.c2
-rw-r--r--sys/kern/uipc_socket.c2
8 files changed, 51 insertions, 38 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);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index f23c756..ecaed6f 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -192,11 +192,7 @@ exit1(td, rv)
* Reset any sigio structures pointing to us as a result of
* F_SETOWN with our pid.
*/
- SIGIO_LOCK();
- PROC_LOCK(p);
funsetownlst(&p->p_sigiolst);
- PROC_UNLOCK(p);
- SIGIO_UNLOCK();
/*
* Close open files and release open-file table.
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 2dde108..8f92331 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -474,16 +474,13 @@ pgdelete(pgrp)
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
- SIGIO_LOCK();
- PGRP_LOCK(pgrp);
-
/*
* Reset any sigio structures pointing to us as a result of
* F_SETOWN with our pgid.
*/
funsetownlst(&pgrp->pg_sigiolst);
- SIGIO_UNLOCK();
+ PGRP_LOCK(pgrp);
if (pgrp->pg_session->s_ttyp != NULL &&
pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
pgrp->pg_session->s_ttyp->t_pgrp = NULL;
diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c
index 568b3fe..2c01568 100644
--- a/sys/kern/subr_log.c
+++ b/sys/kern/subr_log.c
@@ -118,7 +118,7 @@ logclose(dev_t dev, int flag, int mode, struct thread *td)
log_open = 0;
callout_stop(&logsoftc.sc_callout);
logsoftc.sc_state = 0;
- funsetown(logsoftc.sc_sigio);
+ funsetown(&logsoftc.sc_sigio);
return (0);
}
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 59cf2ca..fcc9b53 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -189,6 +189,7 @@ static struct witness_order_list_entry order_lists[] = {
{ "Giant", &lock_class_mtx_sleep },
{ "proctree", &lock_class_sx },
{ "allproc", &lock_class_sx },
+ { "sigio lock", &lock_class_mtx_sleep },
{ "process group", &lock_class_mtx_sleep },
{ "process lock", &lock_class_mtx_sleep },
{ "session", &lock_class_mtx_sleep },
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index d0682fa..c79f9ec 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1246,7 +1246,7 @@ pipe_close(fp, td)
fp->f_ops = &badfileops;
fp->f_data = NULL;
- funsetown(cpipe->pipe_sigio);
+ funsetown(&cpipe->pipe_sigio);
pipeclose(cpipe);
return (0);
}
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 7b3459a..5c7719b 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -246,7 +246,7 @@ ttyclose(tp)
{
int s;
- funsetown(tp->t_sigio);
+ funsetown(&tp->t_sigio);
s = spltty();
if (constty == tp)
constty = NULL;
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 33f8a4d..4bbc6e2 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -305,7 +305,7 @@ soclose(so)
int s = splnet(); /* conservative */
int error = 0;
- funsetown(so->so_sigio);
+ funsetown(&so->so_sigio);
if (so->so_options & SO_ACCEPTCONN) {
struct socket *sp, *sonext;
OpenPOWER on IntegriCloud