Revert most of revision 1.235 and fix the problem a different way. We

can't acquire an sx lock in ttyinfo() because ttyinfo() can be called
from interrupt handlers (such as atkbd_intr()).  Instead, go back to
locking the process group while we pick a thread to display information for
and hold that lock until after we drop sched_lock to make sure the
process doesn't exit out from under us.  sched_lock ensures that the
specific thread from that process doesn't go away.  To protect against
the process exiting after we drop the proc lock but before we dereference
it to lookup the pid and p_comm in the call to ttyprintf(), we now copy
the pid and p_comm to local variables while holding the proc lock.

This problem was found by the recently added TD_NO_SLEEPING assertions for
interrupt handlers.

Tested by:	emaste
MFC after:	1 week
This commit is contained in:
John Baldwin 2005-10-27 16:47:28 +00:00
parent f373190c49
commit 2851f51eb1

View File

@ -2531,6 +2531,8 @@ ttyinfo(struct tty *tp)
const char *stateprefix, *state;
long rss;
int load, pctcpu;
pid_t pid;
char comm[MAXCOMLEN + 1];
if (ttycheckoutq(tp,0) == 0)
return;
@ -2553,9 +2555,9 @@ ttyinfo(struct tty *tp)
tp->t_rocount = 0;
return;
}
sx_slock(&proctree_lock);
if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL) {
sx_sunlock(&proctree_lock);
PGRP_LOCK(tp->t_pgrp);
if (LIST_EMPTY(&tp->t_pgrp->pg_members)) {
PGRP_UNLOCK(tp->t_pgrp);
ttyprintf(tp, "empty foreground process group\n");
tp->t_rocount = 0;
return;
@ -2569,8 +2571,9 @@ ttyinfo(struct tty *tp)
* copy of the state, but may increase interrupt latency
* too much.
*/
pick = NULL;
mtx_lock_spin(&sched_lock);
for (pick = NULL; p != NULL; p = LIST_NEXT(p, p_pglist))
LIST_FOREACH(p, &tp->t_pgrp->pg_members, p_pglist)
if (proc_compare(pick, p))
pick = p;
@ -2580,7 +2583,7 @@ ttyinfo(struct tty *tp)
#else
if (td == NULL) {
mtx_unlock_spin(&sched_lock);
sx_sunlock(&proctree_lock);
PGRP_UNLOCK(tp->t_pgrp);
ttyprintf(tp, "foreground process without thread\n");
tp->t_rocount = 0;
return;
@ -2613,18 +2616,20 @@ ttyinfo(struct tty *tp)
rss = pgtok(vmspace_resident_count(pick->p_vmspace));
mtx_unlock_spin(&sched_lock);
PROC_LOCK(pick);
PGRP_UNLOCK(tp->t_pgrp);
calcru(pick, &utime, &stime);
pid = pick->p_pid;
bcopy(pick->p_comm, comm, sizeof(comm));
PROC_UNLOCK(pick);
/* Print command, pid, state, utime, stime, %cpu, and rss. */
ttyprintf(tp,
" cmd: %s %d [%s%s] %ld.%02ldu %ld.%02lds %d%% %ldk\n",
pick->p_comm, pick->p_pid, stateprefix, state,
comm, pid, stateprefix, state,
(long)utime.tv_sec, utime.tv_usec / 10000,
(long)stime.tv_sec, stime.tv_usec / 10000,
pctcpu / 100, rss);
tp->t_rocount = 0;
sx_sunlock(&proctree_lock);
}
/*