Lock struct pgrp, session and sigio.
New locks are: - pgrpsess_lock which locks the whole pgrps and sessions, - pg_mtx which protects the pgrp members, and - s_mtx which protects the session members. Please refer to sys/proc.h for the coverage of these locks. Changes on the pgrp/session interface: - pgfind() needs the pgrpsess_lock held. - The caller of enterpgrp() is responsible to allocate a new pgrp and session. - Call enterthispgrp() in order to enter an existing pgrp. - pgsignal() requires a pgrp lock held. Reviewed by: jhb, alfred Tested on: cvsup.jp.FreeBSD.org (which is a quad-CPU machine running -current)
This commit is contained in:
parent
4aaca88542
commit
f591779bb5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=91140
@ -94,13 +94,11 @@
|
||||
|
||||
#define INIT_IN(in, op, ident, p) \
|
||||
(in)->opcode = (op); \
|
||||
if (p) \
|
||||
PROC_LOCK(p); \
|
||||
PGRPSESS_SLOCK(); \
|
||||
(in)->pid = p ? p->p_pid : -1; \
|
||||
(in)->pgid = p ? p->p_pgid : -1; \
|
||||
(in)->sid = (p && p->p_session && p->p_session->s_leader) ? (p->p_session->s_leader->p_pid) : -1; \
|
||||
if (p) \
|
||||
PROC_UNLOCK(p); \
|
||||
PGRPSESS_SUNLOCK(); \
|
||||
if (ident != NOCRED) { \
|
||||
(in)->cred.cr_uid = ident->cr_uid; \
|
||||
(in)->cred.cr_groupid = ident->cr_gid; \
|
||||
|
@ -494,9 +494,9 @@ linprocfs_doprocstat(PFS_FILL_ARGS)
|
||||
PS_ADD("statr", "%c", '0'); /* XXX */
|
||||
PROC_LOCK(p);
|
||||
PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
|
||||
PROC_UNLOCK(p);
|
||||
PS_ADD("pgrp", "%d", p->p_pgid);
|
||||
PS_ADD("session", "%d", p->p_session->s_sid);
|
||||
PROC_UNLOCK(p);
|
||||
PS_ADD("tty", "%d", 0); /* XXX */
|
||||
PS_ADD("tpgid", "%d", 0); /* XXX */
|
||||
PS_ADD("flags", "%u", 0); /* XXX */
|
||||
|
@ -144,12 +144,13 @@ linux_open(struct thread *td, struct linux_open_args *args)
|
||||
fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
|
||||
fdrop(fp, td);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
PROC_UNLOCK(p);
|
||||
#ifdef DEBUG
|
||||
if (ldebug(open))
|
||||
printf(LMSG("open returns error %d"), error);
|
||||
#endif
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1017,7 +1017,9 @@ svr4_sys_pgrpsys(td, uap)
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
case 0: /* getpgrp() */
|
||||
PROC_LOCK(p);
|
||||
*retval = p->p_pgrp->pg_id;
|
||||
PROC_UNLOCK(p);
|
||||
return 0;
|
||||
|
||||
case 2: /* getsid(pid) */
|
||||
@ -1222,7 +1224,9 @@ svr4_sys_waitsys(td, uap)
|
||||
break;
|
||||
|
||||
case SVR4_P_PGID:
|
||||
PROC_LOCK(td->td_proc);
|
||||
SCARG(uap, id) = -td->td_proc->p_pgid;
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
break;
|
||||
|
||||
case SVR4_P_ALL:
|
||||
@ -1283,8 +1287,12 @@ svr4_sys_waitsys(td, uap)
|
||||
if (q->p_oppid != q->p_pptr->p_pid) {
|
||||
PROC_UNLOCK(q);
|
||||
t = pfind(q->p_oppid);
|
||||
if (t == NULL) {
|
||||
t = initproc;
|
||||
PROC_LOCK(initproc);
|
||||
}
|
||||
PROC_LOCK(q);
|
||||
proc_reparent(q, t ? t : initproc);
|
||||
proc_reparent(q, t);
|
||||
q->p_oppid = 0;
|
||||
q->p_flag &= ~(P_TRACED | P_WAITED);
|
||||
PROC_UNLOCK(q);
|
||||
|
@ -36,6 +36,11 @@
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/fbio.h>
|
||||
#include <sys/consio.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <dev/fb/fbreg.h>
|
||||
#include <dev/syscons/syscons.h>
|
||||
@ -228,7 +233,11 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
|
||||
|| tp->t_winsize.ws_row != scp->ysize) {
|
||||
tp->t_winsize.ws_col = scp->xsize;
|
||||
tp->t_winsize.ws_row = scp->ysize;
|
||||
pgsignal(tp->t_pgrp, SIGWINCH, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, SIGWINCH, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -291,7 +300,11 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
|
||||
|| tp->t_winsize.ws_ypixel != scp->ypixel) {
|
||||
tp->t_winsize.ws_xpixel = scp->xpixel;
|
||||
tp->t_winsize.ws_ypixel = scp->ypixel;
|
||||
pgsignal(tp->t_pgrp, SIGWINCH, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, SIGWINCH, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -423,7 +436,11 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
|
||||
|| tp->t_winsize.ws_row != scp->ysize) {
|
||||
tp->t_winsize.ws_col = scp->xsize;
|
||||
tp->t_winsize.ws_row = scp->ysize;
|
||||
pgsignal(tp->t_pgrp, SIGWINCH, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, SIGWINCH, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -94,13 +94,11 @@
|
||||
|
||||
#define INIT_IN(in, op, ident, p) \
|
||||
(in)->opcode = (op); \
|
||||
if (p) \
|
||||
PROC_LOCK(p); \
|
||||
PGRPSESS_SLOCK(); \
|
||||
(in)->pid = p ? p->p_pid : -1; \
|
||||
(in)->pgid = p ? p->p_pgid : -1; \
|
||||
(in)->sid = (p && p->p_session && p->p_session->s_leader) ? (p->p_session->s_leader->p_pid) : -1; \
|
||||
if (p) \
|
||||
PROC_UNLOCK(p); \
|
||||
PGRPSESS_SUNLOCK(); \
|
||||
if (ident != NOCRED) { \
|
||||
(in)->cred.cr_uid = ident->cr_uid; \
|
||||
(in)->cred.cr_groupid = ident->cr_gid; \
|
||||
|
@ -230,8 +230,10 @@ procfs_control(struct proc *curp, struct proc *p, int op)
|
||||
|
||||
pp = pfind(p->p_oppid);
|
||||
PROC_LOCK(p);
|
||||
if (pp)
|
||||
if (pp) {
|
||||
PROC_UNLOCK(pp);
|
||||
proc_reparent(p, pp);
|
||||
}
|
||||
} else
|
||||
PROC_LOCK(p);
|
||||
p->p_oppid = 0;
|
||||
|
@ -48,6 +48,8 @@
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/sbuf.h>
|
||||
@ -75,9 +77,9 @@ procfs_doprocstatus(PFS_FILL_ARGS)
|
||||
pid = p->p_pid;
|
||||
PROC_LOCK(p);
|
||||
ppid = p->p_pptr ? p->p_pptr->p_pid : 0;
|
||||
PROC_UNLOCK(p);
|
||||
pgid = p->p_pgrp->pg_id;
|
||||
sess = p->p_pgrp->pg_session;
|
||||
SESS_LOCK(sess);
|
||||
sid = sess->s_leader ? sess->s_leader->p_pid : 0;
|
||||
|
||||
/* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg
|
||||
@ -106,6 +108,8 @@ procfs_doprocstatus(PFS_FILL_ARGS)
|
||||
sbuf_printf(sb, "%ssldr", sep);
|
||||
sep = ",";
|
||||
}
|
||||
SESS_UNLOCK(sess);
|
||||
PROC_UNLOCK(p);
|
||||
if (*sep != ',') {
|
||||
sbuf_printf(sb, "noflags");
|
||||
}
|
||||
|
@ -35,6 +35,8 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -568,7 +570,7 @@ spec_close(ap)
|
||||
struct thread *a_td;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct vnode *vp = ap->a_vp, *oldvp;
|
||||
struct thread *td = ap->a_td;
|
||||
dev_t dev = vp->v_rdev;
|
||||
|
||||
@ -581,11 +583,18 @@ spec_close(ap)
|
||||
* if the reference count is 2 (this last descriptor
|
||||
* plus the session), release the reference from the session.
|
||||
*/
|
||||
oldvp = NULL;
|
||||
PGRPSESS_XLOCK();
|
||||
if (vcount(vp) == 2 && td && (vp->v_flag & VXLOCK) == 0 &&
|
||||
vp == td->td_proc->p_session->s_ttyvp) {
|
||||
vrele(vp);
|
||||
SESS_LOCK(td->td_proc->p_session);
|
||||
td->td_proc->p_session->s_ttyvp = NULL;
|
||||
SESS_UNLOCK(td->td_proc->p_session);
|
||||
oldvp = vp;
|
||||
}
|
||||
PGRPSESS_XUNLOCK();
|
||||
if (oldvp != NULL)
|
||||
vrele(oldvp);
|
||||
/*
|
||||
* We do not want to really close the device if it
|
||||
* is still in use unless we are trying to close it
|
||||
|
@ -552,6 +552,7 @@ ibcs2_ioctl(td, uap)
|
||||
} ibcs2_jwinsize;
|
||||
|
||||
PROC_LOCK(p);
|
||||
SESS_LOCK(p->p_session);
|
||||
ibcs2_jwinsize.bytex = 80;
|
||||
/* p->p_session->s_ttyp->t_winsize.ws_col; XXX */
|
||||
ibcs2_jwinsize.bytey = 25;
|
||||
@ -560,6 +561,7 @@ ibcs2_ioctl(td, uap)
|
||||
p->p_session->s_ttyp->t_winsize.ws_xpixel;
|
||||
ibcs2_jwinsize.bity =
|
||||
p->p_session->s_ttyp->t_winsize.ws_ypixel;
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
error = copyout((caddr_t)&ibcs2_jwinsize, SCARG(uap, data),
|
||||
sizeof(ibcs2_jwinsize));
|
||||
|
@ -1582,8 +1582,11 @@ set_emulation_mode(struct video_state *svsp, int mode)
|
||||
svsp->scrr_end = svsp->scrr_len - 1;
|
||||
}
|
||||
|
||||
if (svsp->vs_tty && svsp->vs_tty->t_pgrp)
|
||||
if (svsp->vs_tty && svsp->vs_tty->t_pgrp) {
|
||||
PGRP_LOCK(svsp->vs_tty->t_pgrp);
|
||||
pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
|
||||
PGRP_UNLOCK(svsp->vs_tty->t_pgrp);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
@ -1867,8 +1870,11 @@ vt_col(struct video_state *svsp, int cols)
|
||||
(cols == SCR_COL80)? 720: 1056;
|
||||
svsp->vs_tty->t_winsize.ws_ypixel = 400;
|
||||
|
||||
if(svsp->vs_tty->t_pgrp)
|
||||
if(svsp->vs_tty->t_pgrp) {
|
||||
PGRP_LOCK(svsp->vs_tty->t_pgrp);
|
||||
pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
|
||||
PGRP_UNLOCK(svsp->vs_tty->t_pgrp);
|
||||
}
|
||||
}
|
||||
|
||||
reallocate_scrollbuffer(svsp, svsp->scrollback_pages);
|
||||
|
@ -703,8 +703,11 @@ set_screen_size(struct video_state *svsp, int size)
|
||||
svsp->scrr_len = svsp->screen_rows;
|
||||
svsp->scrr_end = svsp->scrr_len - 1;
|
||||
|
||||
if (svsp->vs_tty && svsp->vs_tty->t_pgrp)
|
||||
if (svsp->vs_tty && svsp->vs_tty->t_pgrp) {
|
||||
PGRP_LOCK(svsp->vs_tty->t_pgrp);
|
||||
pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
|
||||
PGRP_UNLOCK(svsp->vs_tty->t_pgrp);
|
||||
}
|
||||
|
||||
reallocate_scrollbuffer(svsp, svsp->scrollback_pages);
|
||||
break;
|
||||
|
@ -305,12 +305,14 @@ proc0_init(void *dummy __unused)
|
||||
*/
|
||||
LIST_INSERT_HEAD(&allproc, p, p_list);
|
||||
LIST_INSERT_HEAD(PIDHASH(0), p, p_hash);
|
||||
mtx_init(&pgrp0.pg_mtx, "process group", MTX_DEF);
|
||||
p->p_pgrp = &pgrp0;
|
||||
LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
|
||||
LIST_INIT(&pgrp0.pg_members);
|
||||
LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
|
||||
|
||||
pgrp0.pg_session = &session0;
|
||||
mtx_init(&session0.s_mtx, "session", MTX_DEF);
|
||||
session0.s_count = 1;
|
||||
session0.s_leader = p;
|
||||
|
||||
|
@ -233,10 +233,14 @@ acct_process(td)
|
||||
acct.ac_gid = p->p_ucred->cr_rgid;
|
||||
|
||||
/* (7) The terminal from which the process was started */
|
||||
PROC_LOCK(p);
|
||||
SESS_LOCK(p->p_session);
|
||||
if ((p->p_flag & P_CONTROLT) && p->p_pgrp->pg_session->s_ttyp)
|
||||
acct.ac_tty = dev2udev(p->p_pgrp->pg_session->s_ttyp->t_dev);
|
||||
else
|
||||
acct.ac_tty = NOUDEV;
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
/* (8) The boolean flags that tell how the process terminated, etc. */
|
||||
acct.ac_flag = p->p_acflag;
|
||||
|
@ -535,15 +535,22 @@ funsetown(sigio)
|
||||
|
||||
if (sigio == NULL)
|
||||
return;
|
||||
|
||||
s = splhigh();
|
||||
*(sigio->sio_myref) = NULL;
|
||||
splx(s);
|
||||
if (sigio->sio_pgid < 0) {
|
||||
if ((sigio)->sio_pgid < 0) {
|
||||
struct pgrp *pg = (sigio)->sio_pgrp;
|
||||
PGRP_LOCK(pg);
|
||||
SLIST_REMOVE(&sigio->sio_pgrp->pg_sigiolst, sigio,
|
||||
sigio, sio_pgsigio);
|
||||
} else /* if ((*sigiop)->sio_pgid > 0) */ {
|
||||
PGRP_UNLOCK(pg);
|
||||
} else {
|
||||
struct proc *p = (sigio)->sio_proc;
|
||||
PROC_LOCK(p);
|
||||
SLIST_REMOVE(&sigio->sio_proc->p_sigiolst, sigio,
|
||||
sigio, sio_pgsigio);
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
crfree(sigio->sio_ucred);
|
||||
FREE(sigio, M_SIGIO);
|
||||
@ -554,10 +561,52 @@ void
|
||||
funsetownlst(sigiolst)
|
||||
struct sigiolst *sigiolst;
|
||||
{
|
||||
int s;
|
||||
struct sigio *sigio;
|
||||
struct proc *p;
|
||||
struct pgrp *pg;
|
||||
|
||||
while ((sigio = SLIST_FIRST(sigiolst)) != NULL)
|
||||
funsetown(sigio);
|
||||
sigio = SLIST_FIRST(sigiolst);
|
||||
if (sigio == NULL)
|
||||
return;
|
||||
|
||||
p = NULL;
|
||||
pg = NULL;
|
||||
|
||||
/*
|
||||
* Every entry of the list should belong
|
||||
* to a single proc or pgrp.
|
||||
*/
|
||||
if (sigio->sio_pgid < 0) {
|
||||
pg = sigio->sio_pgrp;
|
||||
PGRP_LOCK_ASSERT(pg, MA_OWNED);
|
||||
} else /* if (sigio->sio_pgid > 0) */ {
|
||||
p = sigio->sio_proc;
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
}
|
||||
|
||||
while ((sigio = SLIST_FIRST(sigiolst)) != NULL) {
|
||||
s = splhigh();
|
||||
*(sigio->sio_myref) = NULL;
|
||||
splx(s);
|
||||
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);
|
||||
crfree(sigio->sio_ucred);
|
||||
FREE(sigio, M_SIGIO);
|
||||
PGRP_LOCK(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);
|
||||
crfree(sigio->sio_ucred);
|
||||
FREE(sigio, M_SIGIO);
|
||||
PROC_LOCK(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -574,16 +623,28 @@ fsetown(pgid, sigiop)
|
||||
struct proc *proc;
|
||||
struct pgrp *pgrp;
|
||||
struct sigio *sigio;
|
||||
int s;
|
||||
int s, ret;
|
||||
|
||||
if (pgid == 0) {
|
||||
funsetown(*sigiop);
|
||||
return (0);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
/* Allocate and fill in the new sigio out of locks. */
|
||||
MALLOC(sigio, struct sigio *, sizeof(struct sigio), M_SIGIO, M_WAITOK);
|
||||
sigio->sio_pgid = pgid;
|
||||
sigio->sio_ucred = crhold(curthread->td_proc->p_ucred);
|
||||
sigio->sio_myref = sigiop;
|
||||
|
||||
PGRPSESS_SLOCK();
|
||||
if (pgid > 0) {
|
||||
proc = pfind(pgid);
|
||||
if (proc == NULL)
|
||||
return (ESRCH);
|
||||
if (proc == NULL) {
|
||||
ret = ESRCH;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Policy - Don't allow a process to FSETOWN a process
|
||||
@ -593,17 +654,20 @@ fsetown(pgid, sigiop)
|
||||
* restrict FSETOWN to the current process or process
|
||||
* group for maximum safety.
|
||||
*/
|
||||
if (proc->p_session != curthread->td_proc->p_session) {
|
||||
PROC_UNLOCK(proc);
|
||||
return (EPERM);
|
||||
}
|
||||
PROC_UNLOCK(proc);
|
||||
if (proc->p_session != curthread->td_proc->p_session) {
|
||||
ret = EPERM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pgrp = NULL;
|
||||
} else /* if (pgid < 0) */ {
|
||||
pgrp = pgfind(-pgid);
|
||||
if (pgrp == NULL)
|
||||
return (ESRCH);
|
||||
if (pgrp == NULL) {
|
||||
ret = ESRCH;
|
||||
goto fail;
|
||||
}
|
||||
PGRP_UNLOCK(pgrp);
|
||||
|
||||
/*
|
||||
* Policy - Don't allow a process to FSETOWN a process
|
||||
@ -613,27 +677,36 @@ fsetown(pgid, sigiop)
|
||||
* restrict FSETOWN to the current process or process
|
||||
* group for maximum safety.
|
||||
*/
|
||||
if (pgrp->pg_session != curthread->td_proc->p_session)
|
||||
return (EPERM);
|
||||
if (pgrp->pg_session != curthread->td_proc->p_session) {
|
||||
ret = EPERM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
proc = NULL;
|
||||
}
|
||||
funsetown(*sigiop);
|
||||
MALLOC(sigio, struct sigio *, sizeof(struct sigio), M_SIGIO, M_WAITOK);
|
||||
if (pgid > 0) {
|
||||
PROC_LOCK(proc);
|
||||
SLIST_INSERT_HEAD(&proc->p_sigiolst, sigio, sio_pgsigio);
|
||||
sigio->sio_proc = proc;
|
||||
PROC_UNLOCK(proc);
|
||||
} else {
|
||||
PGRP_LOCK(pgrp);
|
||||
SLIST_INSERT_HEAD(&pgrp->pg_sigiolst, sigio, sio_pgsigio);
|
||||
sigio->sio_pgrp = pgrp;
|
||||
PGRP_UNLOCK(pgrp);
|
||||
}
|
||||
sigio->sio_pgid = pgid;
|
||||
sigio->sio_ucred = crhold(curthread->td_proc->p_ucred);
|
||||
sigio->sio_myref = sigiop;
|
||||
PGRPSESS_SUNLOCK();
|
||||
s = splhigh();
|
||||
*sigiop = sigio;
|
||||
splx(s);
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
PGRPSESS_SUNLOCK();
|
||||
crfree(sigio->sio_ucred);
|
||||
FREE(sigio, M_SIGIO);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -125,6 +125,8 @@ exit1(td, rv)
|
||||
register struct vmspace *vm;
|
||||
struct vnode *vtmp;
|
||||
struct exitlist *ep;
|
||||
struct vnode *ttyvp;
|
||||
struct tty *tp;
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
@ -186,7 +188,9 @@ exit1(td, rv)
|
||||
* Reset any sigio structures pointing to us as a result of
|
||||
* F_SETOWN with our pid.
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
funsetownlst(&p->p_sigiolst);
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
/*
|
||||
* Close open files and release open-file table.
|
||||
@ -227,11 +231,11 @@ exit1(td, rv)
|
||||
vm->vm_freer = p;
|
||||
}
|
||||
|
||||
PROC_LOCK(p);
|
||||
PGRPSESS_XLOCK();
|
||||
if (SESS_LEADER(p)) {
|
||||
register struct session *sp = p->p_session;
|
||||
register struct session *sp;
|
||||
|
||||
PROC_UNLOCK(p);
|
||||
sp = p->p_session;
|
||||
if (sp->s_ttyvp) {
|
||||
/*
|
||||
* Controlling process.
|
||||
@ -240,29 +244,48 @@ exit1(td, rv)
|
||||
* and revoke access to controlling terminal.
|
||||
*/
|
||||
if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) {
|
||||
if (sp->s_ttyp->t_pgrp)
|
||||
tp = sp->s_ttyp;
|
||||
if (sp->s_ttyp->t_pgrp) {
|
||||
PGRP_LOCK(sp->s_ttyp->t_pgrp);
|
||||
pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
|
||||
(void) ttywait(sp->s_ttyp);
|
||||
PGRP_UNLOCK(sp->s_ttyp->t_pgrp);
|
||||
}
|
||||
/* XXX tp should be locked. */
|
||||
(void) ttywait(tp);
|
||||
/*
|
||||
* The tty could have been revoked
|
||||
* if we blocked.
|
||||
*/
|
||||
if (sp->s_ttyvp)
|
||||
VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
|
||||
if (sp->s_ttyvp) {
|
||||
ttyvp = sp->s_ttyvp;
|
||||
SESS_LOCK(p->p_session);
|
||||
sp->s_ttyvp = NULL;
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PGRPSESS_XUNLOCK();
|
||||
VOP_REVOKE(ttyvp, REVOKEALL);
|
||||
PGRPSESS_XLOCK();
|
||||
vrele(ttyvp);
|
||||
}
|
||||
}
|
||||
if (sp->s_ttyvp) {
|
||||
ttyvp = sp->s_ttyvp;
|
||||
SESS_LOCK(p->p_session);
|
||||
sp->s_ttyvp = NULL;
|
||||
SESS_UNLOCK(p->p_session);
|
||||
vrele(ttyvp);
|
||||
}
|
||||
if (sp->s_ttyvp)
|
||||
vrele(sp->s_ttyvp);
|
||||
sp->s_ttyvp = NULL;
|
||||
/*
|
||||
* s_ttyp is not zero'd; we use this to indicate
|
||||
* that the session once had a controlling terminal.
|
||||
* (for logging and informational purposes)
|
||||
*/
|
||||
}
|
||||
SESS_LOCK(p->p_session);
|
||||
sp->s_leader = NULL;
|
||||
} else
|
||||
PROC_UNLOCK(p);
|
||||
SESS_UNLOCK(p->p_session);
|
||||
}
|
||||
fixjobc(p, p->p_pgrp, 0);
|
||||
PGRPSESS_XUNLOCK();
|
||||
(void)acct_process(td);
|
||||
#ifdef KTRACE
|
||||
/*
|
||||
@ -309,7 +332,7 @@ exit1(td, rv)
|
||||
q->p_flag &= ~P_TRACED;
|
||||
psignal(q, SIGKILL);
|
||||
}
|
||||
PROC_UNLOCK(q);
|
||||
PROC_UNLOCK(q);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -338,6 +361,7 @@ exit1(td, rv)
|
||||
* notify interested parties of our demise.
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
PROC_LOCK(p->p_pptr);
|
||||
KNOTE(&p->p_klist, NOTE_EXIT);
|
||||
|
||||
/*
|
||||
@ -347,7 +371,9 @@ exit1(td, rv)
|
||||
*/
|
||||
if (p->p_pptr->p_procsig->ps_flag & PS_NOCLDWAIT) {
|
||||
struct proc *pp = p->p_pptr;
|
||||
PROC_UNLOCK(pp);
|
||||
proc_reparent(p, initproc);
|
||||
PROC_LOCK(p->p_pptr);
|
||||
/*
|
||||
* If this was the last child of our parent, notify
|
||||
* parent, so in case he was wait(2)ing, he will
|
||||
@ -357,7 +383,6 @@ exit1(td, rv)
|
||||
wakeup((caddr_t)pp);
|
||||
}
|
||||
|
||||
PROC_LOCK(p->p_pptr);
|
||||
if (p->p_sigparent && p->p_pptr != initproc)
|
||||
psignal(p->p_pptr, p->p_sigparent);
|
||||
else
|
||||
@ -480,8 +505,11 @@ wait1(td, uap, compat)
|
||||
|
||||
mtx_lock(&Giant);
|
||||
q = td->td_proc;
|
||||
if (uap->pid == 0)
|
||||
if (uap->pid == 0) {
|
||||
PROC_LOCK(q);
|
||||
uap->pid = -q->p_pgid;
|
||||
PROC_UNLOCK(q);
|
||||
}
|
||||
if (uap->options &~ (WUNTRACED|WNOHANG|WLINUXCLONE)) {
|
||||
error = EINVAL;
|
||||
goto done2;
|
||||
@ -490,9 +518,12 @@ wait1(td, uap, compat)
|
||||
nfound = 0;
|
||||
sx_slock(&proctree_lock);
|
||||
LIST_FOREACH(p, &q->p_children, p_sibling) {
|
||||
PROC_LOCK(p);
|
||||
if (uap->pid != WAIT_ANY &&
|
||||
p->p_pid != uap->pid && p->p_pgid != -uap->pid)
|
||||
p->p_pid != uap->pid && p->p_pgid != -uap->pid) {
|
||||
PROC_UNLOCK(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* This special case handles a kthread spawned by linux_clone
|
||||
@ -502,7 +533,6 @@ wait1(td, uap, compat)
|
||||
* p_sigparent is not SIGCHLD, and the WLINUXCLONE option
|
||||
* signifies we want to wait for threads and not processes.
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
if ((p->p_sigparent != SIGCHLD) ^
|
||||
((uap->options & WLINUXCLONE) != 0)) {
|
||||
PROC_UNLOCK(p);
|
||||
|
@ -382,12 +382,15 @@ fork1(td, flags, procp)
|
||||
p2 = LIST_FIRST(&allproc);
|
||||
again:
|
||||
for (; p2 != NULL; p2 = LIST_NEXT(p2, p_list)) {
|
||||
PROC_LOCK(p2);
|
||||
while (p2->p_pid == trypid ||
|
||||
p2->p_pgrp->pg_id == trypid ||
|
||||
p2->p_session->s_sid == trypid) {
|
||||
trypid++;
|
||||
if (trypid >= pidchecked)
|
||||
if (trypid >= pidchecked) {
|
||||
PROC_UNLOCK(p2);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
if (p2->p_pid > trypid && pidchecked > p2->p_pid)
|
||||
pidchecked = p2->p_pid;
|
||||
@ -397,6 +400,7 @@ fork1(td, flags, procp)
|
||||
if (p2->p_session->s_sid > trypid &&
|
||||
pidchecked > p2->p_session->s_sid)
|
||||
pidchecked = p2->p_session->s_sid;
|
||||
PROC_UNLOCK(p2);
|
||||
}
|
||||
if (!doingzomb) {
|
||||
doingzomb = 1;
|
||||
@ -559,8 +563,10 @@ fork1(td, flags, procp)
|
||||
* been preserved.
|
||||
*/
|
||||
p2->p_flag |= p1->p_flag & (P_SUGID | P_ALTSTACK);
|
||||
SESS_LOCK(p1->p_session);
|
||||
if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
|
||||
p2->p_flag |= P_CONTROLT;
|
||||
SESS_UNLOCK(p1->p_session);
|
||||
if (flags & RFPPWAIT)
|
||||
p2->p_flag |= P_PPWAIT;
|
||||
|
||||
|
@ -350,16 +350,24 @@ ktrace(td, uap)
|
||||
/*
|
||||
* by process group
|
||||
*/
|
||||
PGRPSESS_SLOCK();
|
||||
pg = pgfind(-uap->pid);
|
||||
if (pg == NULL) {
|
||||
PGRPSESS_SUNLOCK();
|
||||
error = ESRCH;
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* ktrops() may call vrele(). Lock pg_members
|
||||
* by the pgrpsess_lock rather than pg_mtx.
|
||||
*/
|
||||
PGRP_UNLOCK(pg);
|
||||
LIST_FOREACH(p, &pg->pg_members, p_pglist)
|
||||
if (descend)
|
||||
ret |= ktrsetchildren(curp, p, ops, facs, vp);
|
||||
else
|
||||
ret |= ktrops(curp, p, ops, facs, vp);
|
||||
PGRPSESS_SUNLOCK();
|
||||
} else {
|
||||
/*
|
||||
* by pid
|
||||
|
@ -55,14 +55,18 @@
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_zone.h>
|
||||
|
||||
static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
|
||||
MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
|
||||
MALLOC_DEFINE(M_SESSION, "session", "session header");
|
||||
static MALLOC_DEFINE(M_PROC, "proc", "Proc structures");
|
||||
MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures");
|
||||
|
||||
static struct proc *dopfind __P((register pid_t));
|
||||
|
||||
static void doenterpgrp __P((struct proc *, struct pgrp *));
|
||||
|
||||
static void pgdelete __P((struct pgrp *));
|
||||
|
||||
static void orphanpg __P((struct pgrp *pg));
|
||||
static void orphanpg __P((struct pgrp *pg));
|
||||
|
||||
/*
|
||||
* Other process lists
|
||||
@ -75,6 +79,7 @@ struct proclist allproc;
|
||||
struct proclist zombproc;
|
||||
struct sx allproc_lock;
|
||||
struct sx proctree_lock;
|
||||
struct sx pgrpsess_lock;
|
||||
vm_zone_t proc_zone;
|
||||
vm_zone_t ithread_zone;
|
||||
|
||||
@ -88,6 +93,7 @@ procinit()
|
||||
|
||||
sx_init(&allproc_lock, "allproc");
|
||||
sx_init(&proctree_lock, "proctree");
|
||||
sx_init(&pgrpsess_lock, "pgrpsess");
|
||||
LIST_INIT(&allproc);
|
||||
LIST_INIT(&zombproc);
|
||||
pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
|
||||
@ -265,17 +271,30 @@ pfind(pid)
|
||||
register struct proc *p;
|
||||
|
||||
sx_slock(&allproc_lock);
|
||||
p = dopfind(pid);
|
||||
sx_sunlock(&allproc_lock);
|
||||
return (p);
|
||||
}
|
||||
|
||||
static struct proc *
|
||||
dopfind(pid)
|
||||
register pid_t pid;
|
||||
{
|
||||
register struct proc *p;
|
||||
|
||||
sx_assert(&allproc_lock, SX_LOCKED);
|
||||
|
||||
LIST_FOREACH(p, PIDHASH(pid), p_hash)
|
||||
if (p->p_pid == pid) {
|
||||
PROC_LOCK(p);
|
||||
break;
|
||||
}
|
||||
sx_sunlock(&allproc_lock);
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate a process group by number
|
||||
* Locate a process group by number.
|
||||
* The caller must hold pgrpsess_lock.
|
||||
*/
|
||||
struct pgrp *
|
||||
pgfind(pgid)
|
||||
@ -283,77 +302,132 @@ pgfind(pgid)
|
||||
{
|
||||
register struct pgrp *pgrp;
|
||||
|
||||
LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash)
|
||||
if (pgrp->pg_id == pgid)
|
||||
PGRPSESS_LOCK_ASSERT(SX_LOCKED);
|
||||
|
||||
LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) {
|
||||
if (pgrp->pg_id == pgid) {
|
||||
PGRP_LOCK(pgrp);
|
||||
return (pgrp);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move p to a new or existing process group (and session)
|
||||
* Create a new process group.
|
||||
* pgid must be equal to the pid of p.
|
||||
* Begin a new session if required.
|
||||
*/
|
||||
int
|
||||
enterpgrp(p, pgid, mksess)
|
||||
enterpgrp(p, pgid, pgrp, sess)
|
||||
register struct proc *p;
|
||||
pid_t pgid;
|
||||
int mksess;
|
||||
struct pgrp *pgrp;
|
||||
struct session *sess;
|
||||
{
|
||||
register struct pgrp *pgrp = pgfind(pgid);
|
||||
struct pgrp *savegrp;
|
||||
struct pgrp *pgrp2;
|
||||
|
||||
KASSERT(pgrp == NULL || !mksess,
|
||||
("enterpgrp: setsid into non-empty pgrp"));
|
||||
PGRPSESS_LOCK_ASSERT(SX_XLOCKED);
|
||||
|
||||
KASSERT(pgrp != NULL, ("enterpgrp: pgrp == NULL"));
|
||||
KASSERT(p->p_pid == pgid,
|
||||
("enterpgrp: new pgrp and pid != pgid"));
|
||||
|
||||
pgrp2 = pgfind(pgid);
|
||||
|
||||
KASSERT(pgrp2 == NULL,
|
||||
("enterpgrp: pgrp with pgid exists"));
|
||||
KASSERT(!SESS_LEADER(p),
|
||||
("enterpgrp: session leader attempted setpgrp"));
|
||||
|
||||
if (pgrp == NULL) {
|
||||
pid_t savepid = p->p_pid;
|
||||
struct proc *np;
|
||||
/*
|
||||
* new process group
|
||||
*/
|
||||
KASSERT(p->p_pid == pgid,
|
||||
("enterpgrp: new pgrp and pid != pgid"));
|
||||
if ((np = pfind(savepid)) == NULL || np != p) {
|
||||
if (np != NULL)
|
||||
PROC_UNLOCK(np);
|
||||
return (ESRCH);
|
||||
}
|
||||
PROC_UNLOCK(np);
|
||||
MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
|
||||
M_WAITOK);
|
||||
if (mksess) {
|
||||
register struct session *sess;
|
||||
mtx_init(&pgrp->pg_mtx, "process group", MTX_DEF);
|
||||
|
||||
/*
|
||||
* new session
|
||||
*/
|
||||
MALLOC(sess, struct session *, sizeof(struct session),
|
||||
M_SESSION, M_WAITOK);
|
||||
sess->s_leader = p;
|
||||
sess->s_sid = p->p_pid;
|
||||
sess->s_count = 1;
|
||||
sess->s_ttyvp = NULL;
|
||||
sess->s_ttyp = NULL;
|
||||
bcopy(p->p_session->s_login, sess->s_login,
|
||||
if (sess != NULL) {
|
||||
/*
|
||||
* new session
|
||||
*/
|
||||
mtx_init(&sess->s_mtx, "session", MTX_DEF);
|
||||
PROC_LOCK(p);
|
||||
p->p_flag &= ~P_CONTROLT;
|
||||
PROC_UNLOCK(p);
|
||||
PGRP_LOCK(pgrp);
|
||||
sess->s_leader = p;
|
||||
sess->s_sid = p->p_pid;
|
||||
sess->s_count = 1;
|
||||
sess->s_ttyvp = NULL;
|
||||
sess->s_ttyp = NULL;
|
||||
bcopy(p->p_session->s_login, sess->s_login,
|
||||
sizeof(sess->s_login));
|
||||
PROC_LOCK(p);
|
||||
p->p_flag &= ~P_CONTROLT;
|
||||
PROC_UNLOCK(p);
|
||||
pgrp->pg_session = sess;
|
||||
KASSERT(p == curproc,
|
||||
("enterpgrp: mksession and p != curproc"));
|
||||
} else {
|
||||
pgrp->pg_session = p->p_session;
|
||||
pgrp->pg_session->s_count++;
|
||||
}
|
||||
pgrp->pg_id = pgid;
|
||||
LIST_INIT(&pgrp->pg_members);
|
||||
LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
|
||||
pgrp->pg_jobc = 0;
|
||||
SLIST_INIT(&pgrp->pg_sigiolst);
|
||||
} else if (pgrp == p->p_pgrp)
|
||||
return (0);
|
||||
pgrp->pg_session = sess;
|
||||
KASSERT(p == curproc,
|
||||
("enterpgrp: mksession and p != curproc"));
|
||||
} else {
|
||||
pgrp->pg_session = p->p_session;
|
||||
SESS_LOCK(pgrp->pg_session);
|
||||
pgrp->pg_session->s_count++;
|
||||
SESS_UNLOCK(pgrp->pg_session);
|
||||
PGRP_LOCK(pgrp);
|
||||
}
|
||||
pgrp->pg_id = pgid;
|
||||
LIST_INIT(&pgrp->pg_members);
|
||||
|
||||
/*
|
||||
* As we have an exclusive lock of pgrpsess_lock,
|
||||
* this should not deadlock.
|
||||
*/
|
||||
LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
|
||||
pgrp->pg_jobc = 0;
|
||||
SLIST_INIT(&pgrp->pg_sigiolst);
|
||||
PGRP_UNLOCK(pgrp);
|
||||
|
||||
doenterpgrp(p, pgrp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move p to an existing process group
|
||||
*/
|
||||
int
|
||||
enterthispgrp(p, pgrp)
|
||||
register struct proc *p;
|
||||
struct pgrp *pgrp;
|
||||
{
|
||||
PGRPSESS_LOCK_ASSERT(SX_XLOCKED);
|
||||
PROC_LOCK_ASSERT(p, MA_NOTOWNED);
|
||||
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
|
||||
PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED);
|
||||
SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED);
|
||||
KASSERT(pgrp->pg_session == p->p_session,
|
||||
("%s: pgrp's session %p, p->p_session %p.\n",
|
||||
__func__,
|
||||
pgrp->pg_session,
|
||||
p->p_session));
|
||||
KASSERT(pgrp != p->p_pgrp,
|
||||
("%s: p belongs to pgrp.", __func__));
|
||||
|
||||
doenterpgrp(p, pgrp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move p to a process group
|
||||
*/
|
||||
static void
|
||||
doenterpgrp(p, pgrp)
|
||||
struct proc *p;
|
||||
struct pgrp *pgrp;
|
||||
{
|
||||
struct pgrp *savepgrp;
|
||||
|
||||
PGRPSESS_LOCK_ASSERT(SX_XLOCKED);
|
||||
PROC_LOCK_ASSERT(p, MA_NOTOWNED);
|
||||
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
|
||||
PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED);
|
||||
SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED);
|
||||
|
||||
savepgrp = p->p_pgrp;
|
||||
|
||||
/*
|
||||
* Adjust eligibility of affected pgrps to participate in job control.
|
||||
@ -363,15 +437,17 @@ enterpgrp(p, pgid, mksess)
|
||||
fixjobc(p, pgrp, 1);
|
||||
fixjobc(p, p->p_pgrp, 0);
|
||||
|
||||
PGRP_LOCK(pgrp);
|
||||
PGRP_LOCK(savepgrp);
|
||||
PROC_LOCK(p);
|
||||
LIST_REMOVE(p, p_pglist);
|
||||
savegrp = p->p_pgrp;
|
||||
p->p_pgrp = pgrp;
|
||||
LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
|
||||
PROC_UNLOCK(p);
|
||||
if (LIST_EMPTY(&savegrp->pg_members))
|
||||
pgdelete(savegrp);
|
||||
return (0);
|
||||
LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
|
||||
PGRP_UNLOCK(savepgrp);
|
||||
PGRP_UNLOCK(pgrp);
|
||||
if (LIST_EMPTY(&savepgrp->pg_members))
|
||||
pgdelete(savepgrp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -381,15 +457,19 @@ int
|
||||
leavepgrp(p)
|
||||
register struct proc *p;
|
||||
{
|
||||
struct pgrp *savegrp;
|
||||
struct pgrp *savepgrp;
|
||||
|
||||
PGRPSESS_XLOCK();
|
||||
savepgrp = p->p_pgrp;
|
||||
PGRP_LOCK(savepgrp);
|
||||
PROC_LOCK(p);
|
||||
LIST_REMOVE(p, p_pglist);
|
||||
savegrp = p->p_pgrp;
|
||||
p->p_pgrp = NULL;
|
||||
PROC_UNLOCK(p);
|
||||
if (LIST_EMPTY(&savegrp->pg_members))
|
||||
pgdelete(savegrp);
|
||||
PGRP_UNLOCK(savepgrp);
|
||||
if (LIST_EMPTY(&savepgrp->pg_members))
|
||||
pgdelete(savepgrp);
|
||||
PGRPSESS_XUNLOCK();
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -400,6 +480,13 @@ static void
|
||||
pgdelete(pgrp)
|
||||
register struct pgrp *pgrp;
|
||||
{
|
||||
struct session *savesess;
|
||||
|
||||
PGRPSESS_LOCK_ASSERT(SX_XLOCKED);
|
||||
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
|
||||
SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
|
||||
|
||||
PGRP_LOCK(pgrp);
|
||||
|
||||
/*
|
||||
* Reset any sigio structures pointing to us as a result of
|
||||
@ -411,8 +498,16 @@ pgdelete(pgrp)
|
||||
pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
|
||||
pgrp->pg_session->s_ttyp->t_pgrp = NULL;
|
||||
LIST_REMOVE(pgrp, pg_hash);
|
||||
if (--pgrp->pg_session->s_count == 0)
|
||||
savesess = pgrp->pg_session;
|
||||
SESS_LOCK(savesess);
|
||||
savesess->s_count--;
|
||||
SESS_UNLOCK(savesess);
|
||||
PGRP_UNLOCK(pgrp);
|
||||
if (savesess->s_count == 0) {
|
||||
mtx_destroy(&savesess->s_mtx);
|
||||
FREE(pgrp->pg_session, M_SESSION);
|
||||
}
|
||||
mtx_destroy(&pgrp->pg_mtx);
|
||||
FREE(pgrp, M_PGRP);
|
||||
}
|
||||
|
||||
@ -433,19 +528,30 @@ fixjobc(p, pgrp, entering)
|
||||
int entering;
|
||||
{
|
||||
register struct pgrp *hispgrp;
|
||||
register struct session *mysession = pgrp->pg_session;
|
||||
register struct session *mysession;
|
||||
|
||||
PGRPSESS_LOCK_ASSERT(SX_LOCKED);
|
||||
PROC_LOCK_ASSERT(p, MA_NOTOWNED);
|
||||
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
|
||||
SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
|
||||
|
||||
/*
|
||||
* Check p's parent to see whether p qualifies its own process
|
||||
* group; if so, adjust count for p's process group.
|
||||
*/
|
||||
mysession = pgrp->pg_session;
|
||||
sx_slock(&proctree_lock);
|
||||
if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
|
||||
hispgrp->pg_session == mysession) {
|
||||
PGRP_LOCK(pgrp);
|
||||
if (entering)
|
||||
pgrp->pg_jobc++;
|
||||
else if (--pgrp->pg_jobc == 0)
|
||||
orphanpg(pgrp);
|
||||
else {
|
||||
--pgrp->pg_jobc;
|
||||
if (pgrp->pg_jobc == 0)
|
||||
orphanpg(pgrp);
|
||||
}
|
||||
PGRP_UNLOCK(pgrp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -453,15 +559,21 @@ fixjobc(p, pgrp, entering)
|
||||
* their process groups; if so, adjust counts for children's
|
||||
* process groups.
|
||||
*/
|
||||
LIST_FOREACH(p, &p->p_children, p_sibling)
|
||||
LIST_FOREACH(p, &p->p_children, p_sibling) {
|
||||
if ((hispgrp = p->p_pgrp) != pgrp &&
|
||||
hispgrp->pg_session == mysession &&
|
||||
p->p_stat != SZOMB) {
|
||||
PGRP_LOCK(hispgrp);
|
||||
if (entering)
|
||||
hispgrp->pg_jobc++;
|
||||
else if (--hispgrp->pg_jobc == 0)
|
||||
orphanpg(hispgrp);
|
||||
else {
|
||||
--hispgrp->pg_jobc;
|
||||
if (hispgrp->pg_jobc == 0)
|
||||
orphanpg(hispgrp);
|
||||
}
|
||||
PGRP_UNLOCK(hispgrp);
|
||||
}
|
||||
}
|
||||
sx_sunlock(&proctree_lock);
|
||||
}
|
||||
|
||||
@ -476,6 +588,8 @@ orphanpg(pg)
|
||||
{
|
||||
register struct proc *p;
|
||||
|
||||
PGRP_LOCK_ASSERT(pg, MA_OWNED);
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
|
||||
if (p->p_stat == SSTOP) {
|
||||
@ -619,6 +733,7 @@ fill_kinfo_proc(p, kp)
|
||||
/* ^^^ XXXKSE */
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
sp = NULL;
|
||||
tp = NULL;
|
||||
if (p->p_pgrp) {
|
||||
kp->ki_pgid = p->p_pgrp->pg_id;
|
||||
kp->ki_jobc = p->p_pgrp->pg_jobc;
|
||||
@ -626,15 +741,18 @@ fill_kinfo_proc(p, kp)
|
||||
|
||||
if (sp != NULL) {
|
||||
kp->ki_sid = sp->s_sid;
|
||||
SESS_LOCK(sp);
|
||||
strncpy(kp->ki_login, sp->s_login,
|
||||
sizeof(kp->ki_login) - 1);
|
||||
if (sp->s_ttyvp)
|
||||
kp->ki_kiflag |= KI_CTTY;
|
||||
if (SESS_LEADER(p))
|
||||
kp->ki_kiflag |= KI_SLEADER;
|
||||
tp = sp->s_ttyp;
|
||||
SESS_UNLOCK(sp);
|
||||
}
|
||||
}
|
||||
if ((p->p_flag & P_CONTROLT) && sp && ((tp = sp->s_ttyp) != NULL)) {
|
||||
if ((p->p_flag & P_CONTROLT) && tp != NULL) {
|
||||
kp->ki_tdev = dev2udev(tp->t_dev);
|
||||
kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
|
||||
if (tp->t_session)
|
||||
@ -768,18 +886,32 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
case KERN_PROC_PGRP:
|
||||
/* could do this by traversing pgrp */
|
||||
PROC_LOCK(p);
|
||||
if (p->p_pgrp == NULL ||
|
||||
p->p_pgrp->pg_id != (pid_t)name[0])
|
||||
p->p_pgrp->pg_id != (pid_t)name[0]) {
|
||||
PROC_UNLOCK(p);
|
||||
continue;
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
break;
|
||||
|
||||
case KERN_PROC_TTY:
|
||||
PROC_LOCK(p);
|
||||
if ((p->p_flag & P_CONTROLT) == 0 ||
|
||||
p->p_session == NULL ||
|
||||
p->p_session->s_ttyp == NULL ||
|
||||
dev2udev(p->p_session->s_ttyp->t_dev) !=
|
||||
(udev_t)name[0])
|
||||
p->p_session == NULL) {
|
||||
PROC_UNLOCK(p);
|
||||
continue;
|
||||
}
|
||||
SESS_LOCK(p->p_session);
|
||||
if (p->p_session->s_ttyp == NULL ||
|
||||
dev2udev(p->p_session->s_ttyp->t_dev) !=
|
||||
(udev_t)name[0]) {
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
continue;
|
||||
}
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
break;
|
||||
|
||||
case KERN_PROC_UID:
|
||||
|
@ -51,12 +51,12 @@
|
||||
#include <sys/acct.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -137,10 +137,13 @@ getpgrp(td, uap)
|
||||
struct getpgrp_args *uap;
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
int s;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
s = mtx_lock_giant(kern_giant_proc);
|
||||
PROC_LOCK(p);
|
||||
td->td_retval[0] = p->p_pgrp->pg_id;
|
||||
mtx_unlock(&Giant);
|
||||
PROC_UNLOCK(p);
|
||||
mtx_unlock_giant(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -164,9 +167,11 @@ getpgid(td, uap)
|
||||
|
||||
s = mtx_lock_giant(kern_giant_proc);
|
||||
error = 0;
|
||||
if (uap->pid == 0)
|
||||
if (uap->pid == 0) {
|
||||
PROC_LOCK(p);
|
||||
td->td_retval[0] = p->p_pgrp->pg_id;
|
||||
else if ((pt = pfind(uap->pid)) == NULL)
|
||||
PROC_UNLOCK(p);
|
||||
} else if ((pt = pfind(uap->pid)) == NULL)
|
||||
error = ESRCH;
|
||||
else {
|
||||
error = p_cansee(p, pt);
|
||||
@ -197,12 +202,15 @@ getsid(td, uap)
|
||||
struct proc *p = td->td_proc;
|
||||
struct proc *pt;
|
||||
int error;
|
||||
int s;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
s = mtx_lock_giant(kern_giant_proc);
|
||||
error = 0;
|
||||
if (uap->pid == 0)
|
||||
if (uap->pid == 0) {
|
||||
PROC_LOCK(p);
|
||||
td->td_retval[0] = p->p_session->s_sid;
|
||||
else if ((pt = pfind(uap->pid)) == NULL)
|
||||
PROC_UNLOCK(p);
|
||||
} else if ((pt = pfind(uap->pid)) == NULL)
|
||||
error = ESRCH;
|
||||
else {
|
||||
error = p_cansee(p, pt);
|
||||
@ -210,7 +218,7 @@ getsid(td, uap)
|
||||
td->td_retval[0] = pt->p_session->s_sid;
|
||||
PROC_UNLOCK(pt);
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
mtx_unlock_giant(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -365,19 +373,44 @@ setsid(td, uap)
|
||||
register struct thread *td;
|
||||
struct setsid_args *uap;
|
||||
{
|
||||
struct pgrp *pgrp;
|
||||
int error;
|
||||
struct proc *p = td->td_proc;
|
||||
struct pgrp *newpgrp;
|
||||
struct session *newsess;
|
||||
|
||||
error = 0;
|
||||
pgrp = NULL;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
if (p->p_pgid == p->p_pid || pgfind(p->p_pid))
|
||||
|
||||
MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
|
||||
MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
|
||||
|
||||
PGRPSESS_XLOCK();
|
||||
|
||||
if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) {
|
||||
if (pgrp != NULL)
|
||||
PGRP_UNLOCK(pgrp);
|
||||
error = EPERM;
|
||||
else {
|
||||
(void)enterpgrp(p, p->p_pid, 1);
|
||||
goto fail;
|
||||
} else {
|
||||
(void)enterpgrp(p, p->p_pid, newpgrp, newsess);
|
||||
td->td_retval[0] = p->p_pid;
|
||||
error = 0;
|
||||
}
|
||||
PGRPSESS_XUNLOCK();
|
||||
mtx_unlock(&Giant);
|
||||
return (error);
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
PGRPSESS_XUNLOCK();
|
||||
|
||||
FREE(newpgrp, M_PGRP);
|
||||
FREE(newsess, M_SESSION);
|
||||
|
||||
mtx_unlock(&Giant);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -412,57 +445,92 @@ setpgid(td, uap)
|
||||
register struct proc *targp; /* target process */
|
||||
register struct pgrp *pgrp; /* target pgrp */
|
||||
int error;
|
||||
struct pgrp *newpgrp;
|
||||
|
||||
if (uap->pgid < 0)
|
||||
return (EINVAL);
|
||||
|
||||
error = 0;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
sx_slock(&proctree_lock);
|
||||
|
||||
MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
|
||||
|
||||
PGRPSESS_XLOCK();
|
||||
|
||||
if (uap->pid != 0 && uap->pid != curp->p_pid) {
|
||||
if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
|
||||
sx_slock(&proctree_lock);
|
||||
if ((targp = pfind(uap->pid)) == NULL) {
|
||||
if (targp)
|
||||
PROC_UNLOCK(targp);
|
||||
sx_sunlock(&proctree_lock);
|
||||
error = ESRCH;
|
||||
goto done2;
|
||||
goto fail;
|
||||
}
|
||||
if (!inferior(targp)) {
|
||||
PROC_UNLOCK(targp);
|
||||
sx_sunlock(&proctree_lock);
|
||||
goto fail;
|
||||
}
|
||||
sx_sunlock(&proctree_lock);
|
||||
if ((error = p_cansee(curproc, targp))) {
|
||||
PROC_UNLOCK(targp);
|
||||
goto done2;
|
||||
goto fail;
|
||||
}
|
||||
if (targp->p_pgrp == NULL ||
|
||||
targp->p_session != curp->p_session) {
|
||||
PROC_UNLOCK(targp);
|
||||
error = EPERM;
|
||||
goto done2;
|
||||
goto fail;
|
||||
}
|
||||
if (targp->p_flag & P_EXEC) {
|
||||
PROC_UNLOCK(targp);
|
||||
error = EACCES;
|
||||
goto done2;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
targp = curp;
|
||||
PROC_LOCK(curp); /* XXX: not needed */
|
||||
}
|
||||
if (SESS_LEADER(targp)) {
|
||||
PROC_UNLOCK(targp);
|
||||
} else
|
||||
targp = curp;
|
||||
if (SESS_LEADER(targp)) {
|
||||
error = EPERM;
|
||||
goto done2;
|
||||
goto fail;
|
||||
}
|
||||
if (uap->pgid == 0)
|
||||
uap->pgid = targp->p_pid;
|
||||
else if (uap->pgid != targp->p_pid) {
|
||||
if ((pgrp = pgfind(uap->pgid)) == 0 ||
|
||||
if (uap->pgid == targp->p_pid) {
|
||||
if (targp->p_pgid == uap->pgid)
|
||||
goto done;
|
||||
error = enterpgrp(targp, uap->pgid, newpgrp, NULL);
|
||||
if (error == 0)
|
||||
newpgrp = NULL;
|
||||
} else {
|
||||
if ((pgrp = pgfind(uap->pgid)) == NULL ||
|
||||
pgrp->pg_session != curp->p_session) {
|
||||
PROC_UNLOCK(targp);
|
||||
if (pgrp != NULL)
|
||||
PGRP_UNLOCK(pgrp);
|
||||
error = EPERM;
|
||||
goto done2;
|
||||
goto fail;
|
||||
}
|
||||
if (pgrp == targp->p_pgrp) {
|
||||
PGRP_UNLOCK(pgrp);
|
||||
goto done;
|
||||
}
|
||||
PGRP_UNLOCK(pgrp);
|
||||
error = enterthispgrp(targp, pgrp);
|
||||
}
|
||||
/* XXX: We should probably hold the lock across enterpgrp. */
|
||||
PROC_UNLOCK(targp);
|
||||
error = enterpgrp(targp, uap->pgid, 0);
|
||||
done2:
|
||||
sx_sunlock(&proctree_lock);
|
||||
done:
|
||||
PGRPSESS_XUNLOCK();
|
||||
if (newpgrp != NULL)
|
||||
FREE(newpgrp, M_PGRP);
|
||||
mtx_unlock(&Giant);
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
PGRPSESS_XUNLOCK();
|
||||
|
||||
KASSERT(newpgrp != NULL, ("setpgid failed and newpgrp is null."));
|
||||
FREE(newpgrp, M_PGRP);
|
||||
|
||||
mtx_unlock(&Giant);
|
||||
return (error);
|
||||
}
|
||||
@ -1134,7 +1202,9 @@ issetugid(td, uap)
|
||||
* a user without an exec - programs cannot know *everything*
|
||||
* that libc *might* have put in their data segment.
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
|
||||
PROC_UNLOCK(p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1153,10 +1223,14 @@ __setugid(td, uap)
|
||||
error = 0;
|
||||
switch (uap->flag) {
|
||||
case 0:
|
||||
PROC_LOCK(td->td_proc);
|
||||
td->td_proc->p_flag &= ~P_SUGID;
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
break;
|
||||
case 1:
|
||||
PROC_LOCK(td->td_proc);
|
||||
td->td_proc->p_flag |= P_SUGID;
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
@ -1725,13 +1799,18 @@ getlogin(td, uap)
|
||||
struct getlogin_args *uap;
|
||||
{
|
||||
int error;
|
||||
char login[MAXLOGNAME];
|
||||
struct proc *p = td->td_proc;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
if (uap->namelen > MAXLOGNAME)
|
||||
uap->namelen = MAXLOGNAME;
|
||||
error = copyout((caddr_t) p->p_pgrp->pg_session->s_login,
|
||||
(caddr_t) uap->namebuf, uap->namelen);
|
||||
PROC_LOCK(p);
|
||||
SESS_LOCK(p->p_session);
|
||||
bcopy(p->p_session->s_login, login, uap->namelen);
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
error = copyout((caddr_t) login, (caddr_t) uap->namebuf, uap->namelen);
|
||||
mtx_unlock(&Giant);
|
||||
return(error);
|
||||
}
|
||||
@ -1764,9 +1843,16 @@ setlogin(td, uap)
|
||||
sizeof(logintmp), (size_t *)0);
|
||||
if (error == ENAMETOOLONG)
|
||||
error = EINVAL;
|
||||
else if (!error)
|
||||
(void)memcpy(p->p_pgrp->pg_session->s_login, logintmp,
|
||||
else if (!error) {
|
||||
PGRPSESS_XLOCK();
|
||||
PROC_LOCK(p);
|
||||
SESS_LOCK(p->p_session);
|
||||
(void) memcpy(p->p_session->s_login, logintmp,
|
||||
sizeof(logintmp));
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
PGRPSESS_XUNLOCK();
|
||||
}
|
||||
done2:
|
||||
mtx_unlock(&Giant);
|
||||
return (error);
|
||||
|
@ -111,14 +111,25 @@ getpriority(td, uap)
|
||||
case PRIO_PGRP: {
|
||||
register struct pgrp *pg;
|
||||
|
||||
if (uap->who == 0)
|
||||
PGRPSESS_SLOCK();
|
||||
if (uap->who == 0) {
|
||||
pg = curp->p_pgrp;
|
||||
else if ((pg = pgfind(uap->who)) == NULL)
|
||||
break;
|
||||
PGRP_LOCK(pg);
|
||||
} else {
|
||||
pg = pgfind(uap->who);
|
||||
if (pg == NULL) {
|
||||
PGRPSESS_SUNLOCK();
|
||||
break;
|
||||
}
|
||||
}
|
||||
PGRPSESS_SUNLOCK();
|
||||
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
|
||||
PROC_LOCK(p);
|
||||
if (!p_cansee(curp, p) && p->p_ksegrp.kg_nice /* XXXKSE */ < low)
|
||||
low = p->p_ksegrp.kg_nice /* XXXKSE */ ;
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
PGRP_UNLOCK(pg);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -185,16 +196,27 @@ setpriority(td, uap)
|
||||
case PRIO_PGRP: {
|
||||
register struct pgrp *pg;
|
||||
|
||||
if (uap->who == 0)
|
||||
PGRPSESS_SLOCK();
|
||||
if (uap->who == 0) {
|
||||
pg = curp->p_pgrp;
|
||||
else if ((pg = pgfind(uap->who)) == NULL)
|
||||
break;
|
||||
PGRP_LOCK(pg);
|
||||
} else {
|
||||
pg = pgfind(uap->who);
|
||||
if (pg == NULL) {
|
||||
PGRPSESS_SUNLOCK();
|
||||
break;
|
||||
}
|
||||
}
|
||||
PGRPSESS_SUNLOCK();
|
||||
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
|
||||
PROC_LOCK(p);
|
||||
if (!p_cansee(curp, p)) {
|
||||
error = donice(curp, p, uap->prio);
|
||||
found++;
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
PGRP_UNLOCK(pg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1001,16 +1001,21 @@ killpg1(cp, sig, pgid, all)
|
||||
}
|
||||
sx_sunlock(&allproc_lock);
|
||||
} else {
|
||||
if (pgid == 0)
|
||||
PGRPSESS_SLOCK();
|
||||
if (pgid == 0) {
|
||||
/*
|
||||
* zero pgid means send to my process group.
|
||||
*/
|
||||
pgrp = cp->p_pgrp;
|
||||
else {
|
||||
PGRP_LOCK(pgrp);
|
||||
} else {
|
||||
pgrp = pgfind(pgid);
|
||||
if (pgrp == NULL)
|
||||
if (pgrp == NULL) {
|
||||
PGRPSESS_SUNLOCK();
|
||||
return (ESRCH);
|
||||
}
|
||||
}
|
||||
PGRPSESS_SUNLOCK();
|
||||
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
|
||||
PROC_LOCK(p);
|
||||
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM) {
|
||||
@ -1031,6 +1036,7 @@ killpg1(cp, sig, pgid, all)
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
PGRP_UNLOCK(pgrp);
|
||||
}
|
||||
return (nfound ? 0 : ESRCH);
|
||||
}
|
||||
@ -1124,8 +1130,15 @@ gsignal(pgid, sig)
|
||||
{
|
||||
struct pgrp *pgrp;
|
||||
|
||||
if (pgid && (pgrp = pgfind(pgid)))
|
||||
pgsignal(pgrp, sig, 0);
|
||||
if (pgid != 0) {
|
||||
PGRPSESS_SLOCK();
|
||||
pgrp = pgfind(pgid);
|
||||
PGRPSESS_SUNLOCK();
|
||||
if (pgrp != NULL) {
|
||||
pgsignal(pgrp, sig, 0);
|
||||
PGRP_UNLOCK(pgrp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1140,6 +1153,7 @@ pgsignal(pgrp, sig, checkctty)
|
||||
register struct proc *p;
|
||||
|
||||
if (pgrp) {
|
||||
PGRP_LOCK_ASSERT(pgrp, MA_OWNED);
|
||||
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
|
||||
PROC_LOCK(p);
|
||||
if (checkctty == 0 || p->p_flag & P_CONTROLT)
|
||||
@ -1351,11 +1365,10 @@ psignal(p, sig)
|
||||
goto out;
|
||||
SIGDELSET(p->p_siglist, sig);
|
||||
p->p_xstat = sig;
|
||||
if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) {
|
||||
PROC_LOCK(p->p_pptr);
|
||||
PROC_LOCK(p->p_pptr);
|
||||
if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0)
|
||||
psignal(p->p_pptr, SIGCHLD);
|
||||
PROC_UNLOCK(p->p_pptr);
|
||||
}
|
||||
PROC_UNLOCK(p->p_pptr);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
stop(p);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
@ -1629,14 +1642,13 @@ issignal(p)
|
||||
if (prop & SA_STOP) {
|
||||
if (p->p_flag & P_TRACED ||
|
||||
(p->p_pgrp->pg_jobc == 0 &&
|
||||
prop & SA_TTYSTOP))
|
||||
prop & SA_TTYSTOP))
|
||||
break; /* == ignore */
|
||||
p->p_xstat = sig;
|
||||
if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) {
|
||||
PROC_LOCK(p->p_pptr);
|
||||
PROC_LOCK(p->p_pptr);
|
||||
if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0)
|
||||
psignal(p->p_pptr, SIGCHLD);
|
||||
PROC_UNLOCK(p->p_pptr);
|
||||
}
|
||||
PROC_UNLOCK(p->p_pptr);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
stop(p);
|
||||
PROC_UNLOCK(p);
|
||||
@ -2074,7 +2086,7 @@ pgsigio(sigio, sig, checkctty)
|
||||
{
|
||||
if (sigio == NULL)
|
||||
return;
|
||||
|
||||
|
||||
if (sigio->sio_pgid > 0) {
|
||||
PROC_LOCK(sigio->sio_proc);
|
||||
if (CANSIGIO(sigio->sio_ucred, sigio->sio_proc->p_ucred))
|
||||
@ -2083,6 +2095,7 @@ pgsigio(sigio, sig, checkctty)
|
||||
} else if (sigio->sio_pgid < 0) {
|
||||
struct proc *p;
|
||||
|
||||
PGRP_LOCK(sigio->sio_pgrp);
|
||||
LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist) {
|
||||
PROC_LOCK(p);
|
||||
if (CANSIGIO(sigio->sio_ucred, p->p_ucred) &&
|
||||
@ -2090,6 +2103,7 @@ pgsigio(sigio, sig, checkctty)
|
||||
psignal(p, sig);
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
PGRP_UNLOCK(sigio->sio_pgrp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,9 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/msgbuf.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -113,16 +116,28 @@ uprintf(const char *fmt, ...)
|
||||
struct proc *p = td->td_proc;
|
||||
va_list ap;
|
||||
struct putchar_arg pca;
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
if (td && td != PCPU_GET(idlethread) && p->p_flag & P_CONTROLT &&
|
||||
p->p_session->s_ttyvp) {
|
||||
va_start(ap, fmt);
|
||||
pca.tty = p->p_session->s_ttyp;
|
||||
pca.flags = TOTTY;
|
||||
retval = kvprintf(fmt, putchar, &pca, 10, ap);
|
||||
va_end(ap);
|
||||
if (td == NULL || td == PCPU_GET(idlethread))
|
||||
return (0);
|
||||
|
||||
p = td->td_proc;
|
||||
PROC_LOCK(p);
|
||||
if ((p->p_flag & P_CONTROLT) == 0) {
|
||||
PROC_UNLOCK(p);
|
||||
return (0);
|
||||
}
|
||||
SESS_LOCK(p->p_session);
|
||||
pca.tty = p->p_session->s_ttyp;
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
if (pca.tty == NULL)
|
||||
return (0);
|
||||
pca.flags = TOTTY;
|
||||
va_start(ap, fmt);
|
||||
retval = kvprintf(fmt, putchar, &pca, 10, ap);
|
||||
va_end(ap);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
@ -141,13 +156,23 @@ tprintf(struct proc *p, int pri, const char *fmt, ...)
|
||||
|
||||
if (pri != -1)
|
||||
flags |= TOLOG;
|
||||
if (p && p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
|
||||
SESSHOLD(p->p_session);
|
||||
shld++;
|
||||
if (ttycheckoutq(p->p_session->s_ttyp, 0)) {
|
||||
flags |= TOTTY;
|
||||
if (p != NULL) {
|
||||
PGRPSESS_XLOCK();
|
||||
PROC_LOCK(p);
|
||||
if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
|
||||
SESS_LOCK(p->p_session);
|
||||
SESSHOLD(p->p_session);
|
||||
tp = p->p_session->s_ttyp;
|
||||
}
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
shld++;
|
||||
if (ttycheckoutq(tp, 0))
|
||||
flags |= TOTTY;
|
||||
else
|
||||
tp = NULL;
|
||||
} else
|
||||
PROC_UNLOCK(p);
|
||||
PGRPSESS_XUNLOCK();
|
||||
}
|
||||
pca.pri = pri;
|
||||
pca.tty = tp;
|
||||
@ -155,8 +180,13 @@ tprintf(struct proc *p, int pri, const char *fmt, ...)
|
||||
va_start(ap, fmt);
|
||||
retval = kvprintf(fmt, putchar, &pca, 10, ap);
|
||||
va_end(ap);
|
||||
if (shld)
|
||||
if (shld) {
|
||||
PGRPSESS_XLOCK();
|
||||
SESS_LOCK(p->p_session);
|
||||
SESSRELE(p->p_session);
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PGRPSESS_XUNLOCK();
|
||||
}
|
||||
msgbuftrigger = 1;
|
||||
}
|
||||
|
||||
|
@ -188,9 +188,12 @@ static struct lock_list_entry w_locklistdata[LOCK_CHILDCOUNT];
|
||||
|
||||
static struct witness_order_list_entry order_lists[] = {
|
||||
{ "Giant", &lock_class_mtx_sleep },
|
||||
{ "pgrpsess", &lock_class_sx },
|
||||
{ "proctree", &lock_class_sx },
|
||||
{ "allproc", &lock_class_sx },
|
||||
{ "process group", &lock_class_mtx_sleep },
|
||||
{ "process lock", &lock_class_mtx_sleep },
|
||||
{ "session", &lock_class_mtx_sleep },
|
||||
{ "uidinfo hash", &lock_class_mtx_sleep },
|
||||
{ "uidinfo struct", &lock_class_mtx_sleep },
|
||||
{ NULL, NULL },
|
||||
@ -227,6 +230,7 @@ static struct witness_order_list_entry order_lists[] = {
|
||||
|
||||
static const char *dup_list[] = {
|
||||
"process lock",
|
||||
"process group",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -515,10 +515,10 @@ ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
struct proc *pp;
|
||||
|
||||
pp = pfind(p->p_oppid);
|
||||
if (pp != NULL)
|
||||
PROC_UNLOCK(pp);
|
||||
else
|
||||
if (pp == NULL)
|
||||
pp = initproc;
|
||||
else
|
||||
PROC_UNLOCK(pp);
|
||||
PROC_LOCK(p);
|
||||
proc_reparent(p, pp);
|
||||
} else
|
||||
|
179
sys/kern/tty.c
179
sys/kern/tty.c
@ -75,6 +75,7 @@
|
||||
#include <sys/filio.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
#include <sys/ioctl_compat.h>
|
||||
#endif
|
||||
@ -328,7 +329,11 @@ ttyinput(c, tp)
|
||||
return (0);
|
||||
if (ISSET(iflag, BRKINT)) {
|
||||
ttyflush(tp, FREAD | FWRITE);
|
||||
pgsignal(tp->t_pgrp, SIGINT, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, SIGINT, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
goto endcase;
|
||||
}
|
||||
if (ISSET(iflag, PARMRK))
|
||||
@ -406,15 +411,23 @@ ttyinput(c, tp)
|
||||
if (!ISSET(lflag, NOFLSH))
|
||||
ttyflush(tp, FREAD | FWRITE);
|
||||
ttyecho(c, tp);
|
||||
pgsignal(tp->t_pgrp,
|
||||
CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp,
|
||||
CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
goto endcase;
|
||||
}
|
||||
if (CCEQ(cc[VSUSP], c)) {
|
||||
if (!ISSET(lflag, NOFLSH))
|
||||
ttyflush(tp, FREAD);
|
||||
ttyecho(c, tp);
|
||||
pgsignal(tp->t_pgrp, SIGTSTP, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, SIGTSTP, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
goto endcase;
|
||||
}
|
||||
}
|
||||
@ -532,8 +545,11 @@ ttyinput(c, tp)
|
||||
* ^T - kernel info and generate SIGINFO
|
||||
*/
|
||||
if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
|
||||
if (ISSET(lflag, ISIG))
|
||||
if (ISSET(lflag, ISIG) && tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, SIGINFO, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
if (!ISSET(lflag, NOKERNINFO))
|
||||
ttyinfo(tp);
|
||||
goto endcase;
|
||||
@ -752,17 +768,30 @@ ttioctl(tp, cmd, data, flag)
|
||||
case TIOCSETP:
|
||||
case TIOCSLTC:
|
||||
#endif
|
||||
PGRPSESS_SLOCK();
|
||||
PROC_LOCK(p);
|
||||
while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) &&
|
||||
!SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
|
||||
!SIGISMEMBER(p->p_sigmask, SIGTTOU)) {
|
||||
if (p->p_pgrp->pg_jobc == 0)
|
||||
if (p->p_pgrp->pg_jobc == 0) {
|
||||
PROC_UNLOCK(p);
|
||||
PGRPSESS_SUNLOCK();
|
||||
return (EIO);
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
PGRP_LOCK(p->p_pgrp);
|
||||
pgsignal(p->p_pgrp, SIGTTOU, 1);
|
||||
PGRP_UNLOCK(p->p_pgrp);
|
||||
error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, "ttybg1",
|
||||
0);
|
||||
if (error)
|
||||
if (error) {
|
||||
PGRPSESS_SUNLOCK();
|
||||
return (error);
|
||||
}
|
||||
PROC_LOCK(p);
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
PGRPSESS_SUNLOCK();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1012,22 +1041,44 @@ ttioctl(tp, cmd, data, flag)
|
||||
break;
|
||||
case TIOCSCTTY: /* become controlling tty */
|
||||
/* Session ctty vnode pointer set in vnode layer. */
|
||||
PGRPSESS_XLOCK();
|
||||
if (!SESS_LEADER(p) ||
|
||||
((p->p_session->s_ttyvp || tp->t_session) &&
|
||||
(tp->t_session != p->p_session)))
|
||||
(tp->t_session != p->p_session))) {
|
||||
PGRPSESS_XUNLOCK();
|
||||
return (EPERM);
|
||||
}
|
||||
tp->t_session = p->p_session;
|
||||
tp->t_pgrp = p->p_pgrp;
|
||||
SESS_LOCK(p->p_session);
|
||||
p->p_session->s_ttyp = tp;
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_LOCK(p);
|
||||
p->p_flag |= P_CONTROLT;
|
||||
PROC_UNLOCK(p);
|
||||
PGRPSESS_XUNLOCK();
|
||||
break;
|
||||
case TIOCSPGRP: { /* set pgrp of tty */
|
||||
register struct pgrp *pgrp = pgfind(*(int *)data);
|
||||
register struct pgrp *pgrp;
|
||||
|
||||
if (!isctty(p, tp))
|
||||
PGRPSESS_SLOCK();
|
||||
pgrp = pgfind(*(int *)data);
|
||||
if (!isctty(p, tp)) {
|
||||
if (pgrp != NULL)
|
||||
PGRP_UNLOCK(pgrp);
|
||||
PGRPSESS_SUNLOCK();
|
||||
return (ENOTTY);
|
||||
else if (pgrp == NULL || pgrp->pg_session != p->p_session)
|
||||
}
|
||||
if (pgrp == NULL) {
|
||||
PGRPSESS_SUNLOCK();
|
||||
return (EPERM);
|
||||
}
|
||||
PGRP_UNLOCK(pgrp);
|
||||
if (pgrp->pg_session != p->p_session) {
|
||||
PGRPSESS_SUNLOCK();
|
||||
return (EPERM);
|
||||
}
|
||||
PGRPSESS_SUNLOCK();
|
||||
tp->t_pgrp = pgrp;
|
||||
break;
|
||||
}
|
||||
@ -1040,7 +1091,11 @@ ttioctl(tp, cmd, data, flag)
|
||||
if (bcmp((caddr_t)&tp->t_winsize, data,
|
||||
sizeof (struct winsize))) {
|
||||
tp->t_winsize = *(struct winsize *)data;
|
||||
pgsignal(tp->t_pgrp, SIGWINCH, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, SIGWINCH, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIOCSDRAINWAIT:
|
||||
@ -1459,13 +1514,17 @@ ttymodem(tp, flag)
|
||||
!ISSET(tp->t_cflag, CLOCAL)) {
|
||||
SET(tp->t_state, TS_ZOMBIE);
|
||||
CLR(tp->t_state, TS_CONNECTED);
|
||||
if (tp->t_session && tp->t_session->s_leader) {
|
||||
struct proc *p;
|
||||
if (tp->t_session) {
|
||||
PGRPSESS_SLOCK();
|
||||
if (tp->t_session->s_leader) {
|
||||
struct proc *p;
|
||||
|
||||
p = tp->t_session->s_leader;
|
||||
PROC_LOCK(p);
|
||||
psignal(p, SIGHUP);
|
||||
PROC_UNLOCK(p);
|
||||
p = tp->t_session->s_leader;
|
||||
PROC_LOCK(p);
|
||||
psignal(p, SIGHUP);
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
PGRPSESS_SUNLOCK();
|
||||
}
|
||||
ttyflush(tp, FREAD | FWRITE);
|
||||
return (0);
|
||||
@ -1549,11 +1608,20 @@ ttread(tp, uio, flag)
|
||||
*/
|
||||
if (isbackground(p, tp)) {
|
||||
splx(s);
|
||||
PGRPSESS_SLOCK();
|
||||
PROC_LOCK(p);
|
||||
if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
|
||||
SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
|
||||
(p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0)
|
||||
(p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) {
|
||||
PROC_UNLOCK(p);
|
||||
PGRPSESS_SUNLOCK();
|
||||
return (EIO);
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
PGRP_LOCK(p->p_pgrp);
|
||||
PGRPSESS_SUNLOCK();
|
||||
pgsignal(p->p_pgrp, SIGTTIN, 1);
|
||||
PGRP_UNLOCK(p->p_pgrp);
|
||||
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -1727,7 +1795,11 @@ ttread(tp, uio, flag)
|
||||
*/
|
||||
if (CCEQ(cc[VDSUSP], c) &&
|
||||
ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
|
||||
pgsignal(tp->t_pgrp, SIGTSTP, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, SIGTSTP, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
if (first) {
|
||||
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
|
||||
"ttybg3", 0);
|
||||
@ -1855,19 +1927,30 @@ ttwrite(tp, uio, flag)
|
||||
* Hang the process if it's in the background.
|
||||
*/
|
||||
p = curproc;
|
||||
PGRPSESS_SLOCK();
|
||||
PROC_LOCK(p);
|
||||
if (isbackground(p, tp) &&
|
||||
ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) &&
|
||||
!SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
|
||||
!SIGISMEMBER(p->p_sigmask, SIGTTOU)) {
|
||||
if (p->p_pgrp->pg_jobc == 0) {
|
||||
PROC_UNLOCK(p);
|
||||
PGRPSESS_SUNLOCK();
|
||||
error = EIO;
|
||||
goto out;
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
PGRP_LOCK(p->p_pgrp);
|
||||
PGRPSESS_SUNLOCK();
|
||||
pgsignal(p->p_pgrp, SIGTTOU, 1);
|
||||
PGRP_UNLOCK(p->p_pgrp);
|
||||
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg4", 0);
|
||||
if (error)
|
||||
goto out;
|
||||
goto loop;
|
||||
} else {
|
||||
PROC_UNLOCK(p);
|
||||
PGRPSESS_SUNLOCK();
|
||||
}
|
||||
/*
|
||||
* Process the user's data in at most OBUFSIZ chunks. Perform any
|
||||
@ -2328,38 +2411,44 @@ ttyinfo(tp)
|
||||
ttyprintf(tp, "not a controlling terminal\n");
|
||||
else if (tp->t_pgrp == NULL)
|
||||
ttyprintf(tp, "no foreground process group\n");
|
||||
else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0)
|
||||
ttyprintf(tp, "empty foreground process group\n");
|
||||
else {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) {
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
ttyprintf(tp, "empty foreground process group\n");
|
||||
} else {
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
|
||||
/* Pick interesting process. */
|
||||
for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist))
|
||||
if (proc_compare(pick, p))
|
||||
pick = p;
|
||||
/* Pick interesting process. */
|
||||
for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist))
|
||||
if (proc_compare(pick, p))
|
||||
pick = p;
|
||||
|
||||
td = FIRST_THREAD_IN_PROC(pick);
|
||||
stmp = pick->p_stat == SRUN ? "running" : /* XXXKSE */
|
||||
td->td_wmesg ? td->td_wmesg : "iowait";
|
||||
calcru(pick, &utime, &stime, NULL);
|
||||
ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT ||
|
||||
pick->p_stat == SZOMB ? 0 :
|
||||
pgtok(vmspace_resident_count(pick->p_vmspace));
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
td = FIRST_THREAD_IN_PROC(pick);
|
||||
stmp = pick->p_stat == SRUN ? "running" : /* XXXKSE */
|
||||
td->td_wmesg ? td->td_wmesg : "iowait";
|
||||
calcru(pick, &utime, &stime, NULL);
|
||||
ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT ||
|
||||
pick->p_stat == SZOMB ? 0 :
|
||||
pgtok(vmspace_resident_count(pick->p_vmspace));
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
||||
ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
|
||||
stmp);
|
||||
ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
|
||||
stmp);
|
||||
|
||||
/* Print user time. */
|
||||
ttyprintf(tp, "%ld.%02ldu ",
|
||||
(long)utime.tv_sec, utime.tv_usec / 10000);
|
||||
/* Print user time. */
|
||||
ttyprintf(tp, "%lld.%02ldu ",
|
||||
utime.tv_sec, utime.tv_usec / 10000);
|
||||
|
||||
/* Print system time. */
|
||||
ttyprintf(tp, "%ld.%02lds ",
|
||||
(long)stime.tv_sec, stime.tv_usec / 10000);
|
||||
/* Print system time. */
|
||||
ttyprintf(tp, "%ld.%02lds ",
|
||||
(long)stime.tv_sec, stime.tv_usec / 10000);
|
||||
|
||||
/* Print percentage cpu, resident set size. */
|
||||
ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp);
|
||||
/* Print percentage cpu, resident set size. */
|
||||
ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp);
|
||||
|
||||
}
|
||||
}
|
||||
tp->t_rocount = 0; /* so pending input will be retyped if BS */
|
||||
}
|
||||
|
@ -41,6 +41,9 @@
|
||||
#include "opt_compat.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
#include <sys/ioctl_compat.h>
|
||||
#endif
|
||||
@ -237,11 +240,19 @@ ptsread(dev, uio, flag)
|
||||
again:
|
||||
if (pti->pt_flags & PF_REMOTE) {
|
||||
while (isbackground(p, tp)) {
|
||||
PGRPSESS_SLOCK();
|
||||
PROC_LOCK(p);
|
||||
if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
|
||||
SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
|
||||
p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT)
|
||||
p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
|
||||
PROC_UNLOCK(p);
|
||||
return (EIO);
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
PGRP_LOCK(p->p_pgrp);
|
||||
PGRPSESS_SUNLOCK();
|
||||
pgsignal(p->p_pgrp, SIGTTIN, 1);
|
||||
PGRP_UNLOCK(p->p_pgrp);
|
||||
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
|
||||
0);
|
||||
if (error)
|
||||
@ -715,7 +726,11 @@ ptyioctl(dev, cmd, data, flag, td)
|
||||
return(EINVAL);
|
||||
if ((tp->t_lflag&NOFLSH) == 0)
|
||||
ttyflush(tp, FREAD|FWRITE);
|
||||
pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
|
||||
if (tp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(tp->t_pgrp);
|
||||
pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
|
||||
PGRP_UNLOCK(tp->t_pgrp);
|
||||
}
|
||||
if ((*(unsigned int *)data == SIGINFO) &&
|
||||
((tp->t_lflag&NOKERNINFO) == 0))
|
||||
ttyinfo(tp);
|
||||
|
@ -43,6 +43,8 @@
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ttycom.h>
|
||||
#include <sys/vnode.h>
|
||||
@ -80,9 +82,15 @@ cttyopen(dev, flag, mode, td)
|
||||
int flag, mode;
|
||||
struct thread *td;
|
||||
{
|
||||
struct vnode *ttyvp = cttyvp(td);
|
||||
struct vnode *ttyvp;
|
||||
int error;
|
||||
|
||||
PROC_LOCK(td->td_proc);
|
||||
SESS_LOCK(td->td_proc->p_session);
|
||||
ttyvp = cttyvp(td);
|
||||
SESS_UNLOCK(td->td_proc->p_session);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
|
||||
if (ttyvp == NULL)
|
||||
return (ENXIO);
|
||||
vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||
@ -99,9 +107,15 @@ cttyread(dev, uio, flag)
|
||||
int flag;
|
||||
{
|
||||
struct thread *td = uio->uio_td;
|
||||
register struct vnode *ttyvp = cttyvp(td);
|
||||
register struct vnode *ttyvp;
|
||||
int error;
|
||||
|
||||
PROC_LOCK(td->td_proc);
|
||||
SESS_LOCK(td->td_proc->p_session);
|
||||
ttyvp = cttyvp(td);
|
||||
SESS_UNLOCK(td->td_proc->p_session);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
|
||||
if (ttyvp == NULL)
|
||||
return (EIO);
|
||||
vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||
@ -118,10 +132,16 @@ cttywrite(dev, uio, flag)
|
||||
int flag;
|
||||
{
|
||||
struct thread *td = uio->uio_td;
|
||||
struct vnode *ttyvp = cttyvp(uio->uio_td);
|
||||
struct vnode *ttyvp;
|
||||
struct mount *mp;
|
||||
int error;
|
||||
|
||||
PROC_LOCK(td->td_proc);
|
||||
SESS_LOCK(td->td_proc->p_session);
|
||||
ttyvp = cttyvp(td);
|
||||
SESS_UNLOCK(td->td_proc->p_session);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
|
||||
if (ttyvp == NULL)
|
||||
return (EIO);
|
||||
mp = NULL;
|
||||
@ -144,18 +164,30 @@ cttyioctl(dev, cmd, addr, flag, td)
|
||||
int flag;
|
||||
struct thread *td;
|
||||
{
|
||||
struct vnode *ttyvp = cttyvp(td);
|
||||
struct vnode *ttyvp;
|
||||
int error;
|
||||
|
||||
PROC_LOCK(td->td_proc);
|
||||
SESS_LOCK(td->td_proc->p_session);
|
||||
ttyvp = cttyvp(td);
|
||||
SESS_UNLOCK(td->td_proc->p_session);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
|
||||
if (ttyvp == NULL)
|
||||
return (EIO);
|
||||
if (cmd == TIOCSCTTY) /* don't allow controlling tty to be set */
|
||||
return EINVAL; /* to controlling tty -- infinite recursion */
|
||||
if (cmd == TIOCNOTTY) {
|
||||
if (!SESS_LEADER(td->td_proc)) {
|
||||
PROC_LOCK(td->td_proc);
|
||||
SESS_LOCK(td->td_proc->p_session);
|
||||
error = 0;
|
||||
if (!SESS_LEADER(td->td_proc))
|
||||
td->td_proc->p_flag &= ~P_CONTROLT;
|
||||
return (0);
|
||||
} else
|
||||
return (EINVAL);
|
||||
else
|
||||
error = EINVAL;
|
||||
SESS_UNLOCK(td->td_proc->p_session);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
return (error);
|
||||
}
|
||||
return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, td));
|
||||
}
|
||||
@ -167,7 +199,13 @@ cttypoll(dev, events, td)
|
||||
int events;
|
||||
struct thread *td;
|
||||
{
|
||||
struct vnode *ttyvp = cttyvp(td);
|
||||
struct vnode *ttyvp;
|
||||
|
||||
PROC_LOCK(td->td_proc);
|
||||
SESS_LOCK(td->td_proc->p_session);
|
||||
ttyvp = cttyvp(td);
|
||||
SESS_UNLOCK(td->td_proc->p_session);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
|
||||
if (ttyvp == NULL)
|
||||
/* try operation to get EOF/failure */
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/sysproto.h>
|
||||
@ -741,6 +742,8 @@ aio_daemon(void *uproc)
|
||||
struct proc *curcp, *mycp, *userp;
|
||||
struct vmspace *myvm, *tmpvm;
|
||||
struct thread *td = curthread;
|
||||
struct pgrp *newpgrp;
|
||||
struct session *newsess;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
/*
|
||||
@ -781,7 +784,12 @@ aio_daemon(void *uproc)
|
||||
mycp->p_fd = NULL;
|
||||
|
||||
/* The daemon resides in its own pgrp. */
|
||||
enterpgrp(mycp, mycp->p_pid, 1);
|
||||
MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
|
||||
MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
|
||||
|
||||
PGRPSESS_XLOCK();
|
||||
enterpgrp(mycp, mycp->p_pid, newpgrp, newsess);
|
||||
PGRPSESS_XUNLOCK();
|
||||
|
||||
/* Mark special process type. */
|
||||
mycp->p_flag |= P_SYSTEM;
|
||||
|
@ -619,6 +619,7 @@ vn_ioctl(fp, com, data, td)
|
||||
struct thread *td;
|
||||
{
|
||||
register struct vnode *vp = ((struct vnode *)fp->f_data);
|
||||
struct vnode *vpold;
|
||||
struct vattr vattr;
|
||||
int error;
|
||||
|
||||
@ -656,15 +657,23 @@ vn_ioctl(fp, com, data, td)
|
||||
if (error == 0 && com == TIOCSCTTY) {
|
||||
|
||||
/* Do nothing if reassigning same control tty */
|
||||
if (td->td_proc->p_session->s_ttyvp == vp)
|
||||
PGRPSESS_XLOCK();
|
||||
if (td->td_proc->p_session->s_ttyvp == vp) {
|
||||
PGRPSESS_XUNLOCK();
|
||||
return (0);
|
||||
}
|
||||
|
||||
vpold = td->td_proc->p_session->s_ttyvp;
|
||||
VREF(vp);
|
||||
SESS_LOCK(td->td_proc->p_session);
|
||||
td->td_proc->p_session->s_ttyvp = vp;
|
||||
SESS_UNLOCK(td->td_proc->p_session);
|
||||
|
||||
PGRPSESS_XUNLOCK();
|
||||
|
||||
/* Get rid of reference to old control tty */
|
||||
if (td->td_proc->p_session->s_ttyvp)
|
||||
vrele(td->td_proc->p_session->s_ttyvp);
|
||||
|
||||
td->td_proc->p_session->s_ttyvp = vp;
|
||||
VREF(vp);
|
||||
if (vpold)
|
||||
vrele(vpold);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
@ -83,6 +83,7 @@
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
@ -1076,9 +1077,13 @@ sl_keepalive(chan)
|
||||
struct sl_softc *sc = chan;
|
||||
|
||||
if (sc->sc_keepalive) {
|
||||
if (sc->sc_flags & SC_KEEPALIVE)
|
||||
pgsignal (sc->sc_ttyp->t_pgrp, SIGURG, 1);
|
||||
else
|
||||
if (sc->sc_flags & SC_KEEPALIVE) {
|
||||
if (sc->sc_ttyp->t_pgrp != NULL) {
|
||||
PGRP_LOCK(sc->sc_ttyp->t_pgrp);
|
||||
pgsignal (sc->sc_ttyp->t_pgrp, SIGURG, 1);
|
||||
PGRP_UNLOCK(sc->sc_ttyp->t_pgrp);
|
||||
}
|
||||
} else
|
||||
sc->sc_flags |= SC_KEEPALIVE;
|
||||
sc->sc_kahandle = timeout(sl_keepalive, sc, sc->sc_keepalive);
|
||||
} else {
|
||||
|
@ -7306,14 +7306,24 @@ key_getuserfqdn()
|
||||
struct proc *p = curproc;
|
||||
char *q;
|
||||
|
||||
if (!p || !p->p_pgrp || !p->p_pgrp->pg_session)
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
if (!(host = key_getfqdn()))
|
||||
bzero(userfqdn, sizeof(userfqdn));
|
||||
if (!(host = key_getfqdn())) {
|
||||
PROC_UNLOCK(p);
|
||||
return NULL;
|
||||
}
|
||||
PROC_LOCK(p);
|
||||
if (!p->p_pgrp || !p->p_pgrp->pg_session) {
|
||||
PROC_UNLOCK(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* NOTE: s_login may not be-NUL terminated. */
|
||||
bzero(userfqdn, sizeof(userfqdn));
|
||||
bcopy(p->p_pgrp->pg_session->s_login, userfqdn, MAXLOGNAME);
|
||||
SESS_LOCK(p->p_session);
|
||||
bcopy(p->p_session->s_login, userfqdn, MAXLOGNAME);
|
||||
SESS_UNLOCK(p->p_session);
|
||||
PROC_UNLOCK(p);
|
||||
userfqdn[MAXLOGNAME] = '\0'; /* safeguard */
|
||||
q = userfqdn + strlen(userfqdn);
|
||||
*q++ = '@';
|
||||
|
@ -37,6 +37,10 @@
|
||||
#ifndef _SYS_FILE_H_
|
||||
#define _SYS_FILE_H_
|
||||
|
||||
#include <sys/systm.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#ifndef _KERNEL
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/unistd.h>
|
||||
|
@ -110,17 +110,20 @@ struct filedesc0 {
|
||||
* on a device or socket. The structure is placed on an SLIST belonging
|
||||
* to the proc or pgrp so that the entire list may be revoked when the
|
||||
* process exits or the process group disappears.
|
||||
*
|
||||
* (c) const
|
||||
* (pg) locked by either the process or process group lock
|
||||
*/
|
||||
struct sigio {
|
||||
union {
|
||||
struct proc *siu_proc; /* process to receive SIGIO/SIGURG */
|
||||
struct pgrp *siu_pgrp; /* process group to receive ... */
|
||||
struct proc *siu_proc; /* (c) process to receive SIGIO/SIGURG */
|
||||
struct pgrp *siu_pgrp; /* (c) process group to receive ... */
|
||||
} sio_u;
|
||||
SLIST_ENTRY(sigio) sio_pgsigio; /* sigio's for process or group */
|
||||
struct sigio **sio_myref; /* location of the pointer that holds
|
||||
* the reference to this structure */
|
||||
struct ucred *sio_ucred; /* current credentials */
|
||||
pid_t sio_pgid; /* pgid for signals */
|
||||
SLIST_ENTRY(sigio) sio_pgsigio; /* (pg) sigio's for process or group */
|
||||
struct sigio **sio_myref; /* (c) location of the pointer that holds
|
||||
* the reference to this structure */
|
||||
struct ucred *sio_ucred; /* (c) current credentials */
|
||||
pid_t sio_pgid; /* (c) pgid for signals */
|
||||
};
|
||||
#define sio_proc sio_u.siu_proc
|
||||
#define sio_pgrp sio_u.siu_pgrp
|
||||
|
@ -60,27 +60,39 @@
|
||||
|
||||
/*
|
||||
* One structure allocated per session.
|
||||
*
|
||||
* List of locks
|
||||
* (m) locked by s_mtx mtx
|
||||
* (ps) locked by pgrpsess_lock sx
|
||||
* (c) const until freeing
|
||||
*/
|
||||
struct session {
|
||||
int s_count; /* Ref cnt; pgrps in session. */
|
||||
struct proc *s_leader; /* Session leader. */
|
||||
struct vnode *s_ttyvp; /* Vnode of controlling terminal. */
|
||||
struct tty *s_ttyp; /* Controlling terminal. */
|
||||
pid_t s_sid; /* Session ID. */
|
||||
/* Setlogin() name: */
|
||||
int s_count; /* (m) Ref cnt; pgrps in session. */
|
||||
struct proc *s_leader; /* (m, ps) Session leader. */
|
||||
struct vnode *s_ttyvp; /* (m) Vnode of controlling terminal. */
|
||||
struct tty *s_ttyp; /* (m) Controlling terminal. */
|
||||
pid_t s_sid; /* (c) Session ID. */
|
||||
/* (m) Setlogin() name: */
|
||||
char s_login[roundup(MAXLOGNAME, sizeof(long))];
|
||||
struct mtx s_mtx; /* Mutex to protect members */
|
||||
};
|
||||
|
||||
/*
|
||||
* One structure allocated per process group.
|
||||
*
|
||||
* List of locks
|
||||
* (m) locked by pg_mtx mtx
|
||||
* (ps) locked by pgrpsess_lock sx
|
||||
* (c) const until freeing
|
||||
*/
|
||||
struct pgrp {
|
||||
LIST_ENTRY(pgrp) pg_hash; /* Hash chain. */
|
||||
LIST_HEAD(, proc) pg_members; /* Pointer to pgrp members. */
|
||||
struct session *pg_session; /* Pointer to session. */
|
||||
struct sigiolst pg_sigiolst; /* List of sigio sources. */
|
||||
pid_t pg_id; /* Pgrp id. */
|
||||
int pg_jobc; /* # procs qualifying pgrp for job control */
|
||||
LIST_ENTRY(pgrp) pg_hash; /* (ps) Hash chain. */
|
||||
LIST_HEAD(, proc) pg_members; /* (m, ps) Pointer to pgrp members. */
|
||||
struct session *pg_session; /* (c) Pointer to session. */
|
||||
struct sigiolst pg_sigiolst; /* (m) List of sigio sources. */
|
||||
pid_t pg_id; /* (c) Pgrp id. */
|
||||
int pg_jobc; /* (m) # procs qualifying pgrp for job control */
|
||||
struct mtx pg_mtx; /* Mutex to protect members */
|
||||
};
|
||||
|
||||
struct procsig {
|
||||
@ -134,6 +146,7 @@ struct pargs {
|
||||
* l - the attaching proc or attaching proc parent
|
||||
* m - Giant
|
||||
* n - not locked, lazy
|
||||
* o - locked by pgrpsess_lock sx
|
||||
*
|
||||
* If the locking key specifies two identifiers (for example, p_pptr) then
|
||||
* either lock is sufficient for read access, but both locks must be held
|
||||
@ -388,7 +401,7 @@ struct proc {
|
||||
|
||||
pid_t p_pid; /* (b) Process identifier. */
|
||||
LIST_ENTRY(proc) p_hash; /* (d) Hash chain. */
|
||||
LIST_ENTRY(proc) p_pglist; /* (c) List of processes in pgrp. */
|
||||
LIST_ENTRY(proc) p_pglist; /* (g + o) List of processes in pgrp. */
|
||||
struct proc *p_pptr; /* (c + e) Pointer to parent process. */
|
||||
LIST_ENTRY(proc) p_sibling; /* (e) List of sibling processes. */
|
||||
LIST_HEAD(, proc) p_children; /* (e) Pointer to list of children. */
|
||||
@ -406,7 +419,7 @@ struct proc {
|
||||
struct vnode *p_textvp; /* (b) Vnode of executable. */
|
||||
struct mtx p_mtx; /* (k) Lock for this struct. */
|
||||
char p_lock; /* (c) Proclock (prevent swap) count. */
|
||||
struct klist p_klist; /* (c) Knotes attached to this proc. */
|
||||
struct klist p_klist; /* (c) Knotes attached to this proc. */
|
||||
struct sigiolst p_sigiolst; /* (c) List of sigio sources. */
|
||||
int p_sigparent; /* (c) Signal to parent on exit. */
|
||||
sigset_t p_oldsigmask; /* (c) Saved mask from pre sigpause. */
|
||||
@ -427,7 +440,7 @@ struct proc {
|
||||
stack_t p_sigstk; /* (c) Stack ptr and on-stack flag. */
|
||||
int p_magic; /* (b) Magic number. */
|
||||
char p_comm[MAXCOMLEN + 1]; /* (b) Process name. */
|
||||
struct pgrp *p_pgrp; /* (e?/c?) Pointer to process group. */
|
||||
struct pgrp *p_pgrp; /* (c + o) Pointer to process group. */
|
||||
struct sysentvec *p_sysent; /* (b) Syscall dispatch info. */
|
||||
struct pargs *p_args; /* (c) Process arguments. */
|
||||
/* End area that is copied on creation. */
|
||||
@ -515,6 +528,7 @@ struct proc {
|
||||
|
||||
#ifdef MALLOC_DECLARE
|
||||
MALLOC_DECLARE(M_PARGS);
|
||||
MALLOC_DECLARE(M_PGRP);
|
||||
MALLOC_DECLARE(M_SESSION);
|
||||
MALLOC_DECLARE(M_SUBPROC);
|
||||
MALLOC_DECLARE(M_ZOMBIE);
|
||||
@ -599,6 +613,40 @@ sigonstack(size_t sp)
|
||||
#define PROC_LOCKED(p) mtx_owned(&(p)->p_mtx)
|
||||
#define PROC_LOCK_ASSERT(p, type) mtx_assert(&(p)->p_mtx, (type))
|
||||
|
||||
#define PGRPSESS_SLOCK() sx_slock(&pgrpsess_lock)
|
||||
#define PGRPSESS_XLOCK() sx_xlock(&pgrpsess_lock)
|
||||
#define PGRPSESS_SUNLOCK() sx_sunlock(&pgrpsess_lock)
|
||||
#define PGRPSESS_XUNLOCK() sx_xunlock(&pgrpsess_lock)
|
||||
#define PGRPSESS_LOCK_ASSERT(type) sx_assert(&pgrpsess_lock, (type))
|
||||
|
||||
/* Lock and unlock a process group. */
|
||||
#define PGRP_LOCK(pg) mtx_lock(&(pg)->pg_mtx)
|
||||
#define PGRP_UNLOCK(pg) mtx_unlock(&(pg)->pg_mtx)
|
||||
#define PGRP_UNLOCK_NOSWITCH(pg) \
|
||||
mtx_unlock_flags(&(pg)->pg_mtx, MTX_NOSWITCH)
|
||||
#define PGRP_LOCKED(pg) mtx_owned(&(pg)->pg_mtx)
|
||||
#define PGRP_LOCK_ASSERT(pg, type) mtx_assert(&(pg)->pg_mtx, (type))
|
||||
|
||||
#define PGRP_LOCK_PGSIGNAL(pg) \
|
||||
do { \
|
||||
if ((pg) != NULL) \
|
||||
PGRP_LOCK(pg); \
|
||||
} while (0);
|
||||
|
||||
#define PGRP_UNLOCK_PGSIGNAL(pg) \
|
||||
do { \
|
||||
if ((pg) != NULL) \
|
||||
PGRP_UNLOCK(pg); \
|
||||
} while (0);
|
||||
|
||||
/* Lock and unlock a session. */
|
||||
#define SESS_LOCK(s) mtx_lock(&(s)->s_mtx)
|
||||
#define SESS_UNLOCK(s) mtx_unlock(&(s)->s_mtx)
|
||||
#define SESS_UNLOCK_NOSWITCH(s) \
|
||||
mtx_unlock_flags(&(s)->s_mtx, MTX_NOSWITCH)
|
||||
#define SESS_LOCKED(s) mtx_owned(&(s)->s_mtx)
|
||||
#define SESS_LOCK_ASSERT(s, type) mtx_assert(&(s)->s_mtx, (type))
|
||||
|
||||
/* Hold process U-area in memory, normally for ptrace/procfs work. */
|
||||
#define PHOLD(p) do { \
|
||||
PROC_LOCK(p); \
|
||||
@ -631,6 +679,7 @@ extern u_long pgrphash;
|
||||
|
||||
extern struct sx allproc_lock;
|
||||
extern struct sx proctree_lock;
|
||||
extern struct sx pgrpsess_lock;
|
||||
extern struct proc proc0; /* Process slot for swapper. */
|
||||
extern struct thread thread0; /* Primary thread in proc0 */
|
||||
extern int hogticks; /* Limit on kernel cpu hogs. */
|
||||
@ -672,7 +721,8 @@ struct proc *zpfind(pid_t); /* Find zombie process by id. */
|
||||
void ast(struct trapframe *framep);
|
||||
struct thread *choosethread(void);
|
||||
int cr_cansignal(struct ucred *cred, struct proc *proc, int signum);
|
||||
int enterpgrp(struct proc *p, pid_t pgid, int mksess);
|
||||
int enterpgrp __P((struct proc *p, pid_t pgid, struct pgrp *pgrp, struct session *sess));
|
||||
int enterthispgrp __P((struct proc *p, struct pgrp *pgrp));
|
||||
void faultin(struct proc *p);
|
||||
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
|
||||
int fork1(struct thread *, int, struct proc **);
|
||||
|
Loading…
Reference in New Issue
Block a user