Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/tty.c
Show First 20 Lines • Show All 417 Lines • ▼ Show 20 Lines | tty_is_ctty(struct tty *tp, struct proc *p) | ||||
tty_assert_locked(tp); | tty_assert_locked(tp); | ||||
return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT); | return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT); | ||||
} | } | ||||
int | int | ||||
tty_wait_background(struct tty *tp, struct thread *td, int sig) | tty_wait_background(struct tty *tp, struct thread *td, int sig) | ||||
{ | { | ||||
struct proc *p = td->td_proc; | struct proc *p; | ||||
struct pgrp *pg; | struct pgrp *pg; | ||||
ksiginfo_t ksi; | ksiginfo_t ksi; | ||||
int error; | int error; | ||||
MPASS(sig == SIGTTIN || sig == SIGTTOU); | MPASS(sig == SIGTTIN || sig == SIGTTOU); | ||||
tty_assert_locked(tp); | tty_assert_locked(tp); | ||||
p = td->td_proc; | |||||
for (;;) { | for (;;) { | ||||
pg = p->p_pgrp; | |||||
PGRP_LOCK(pg); | |||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
/* | /* | ||||
* pg may no longer be our process group. | |||||
* Re-check after locking. | |||||
*/ | |||||
if (p->p_pgrp != pg) { | |||||
PROC_UNLOCK(p); | |||||
PGRP_UNLOCK(pg); | |||||
continue; | |||||
} | |||||
/* | |||||
* The process should only sleep, when: | * The process should only sleep, when: | ||||
* - This terminal is the controlling terminal | * - This terminal is the controlling terminal | ||||
* - Its process group is not the foreground process | * - Its process group is not the foreground process | ||||
* group | * group | ||||
* - The parent process isn't waiting for the child to | * - The parent process isn't waiting for the child to | ||||
* exit | * exit | ||||
* - the signal to send to the process isn't masked | * - the signal to send to the process isn't masked | ||||
*/ | */ | ||||
if (!tty_is_ctty(tp, p) || p->p_pgrp == tp->t_pgrp) { | if (!tty_is_ctty(tp, p) || p->p_pgrp == tp->t_pgrp) { | ||||
/* Allow the action to happen. */ | /* Allow the action to happen. */ | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
PGRP_UNLOCK(pg); | |||||
return (0); | return (0); | ||||
} | } | ||||
if (SIGISMEMBER(p->p_sigacts->ps_sigignore, sig) || | if (SIGISMEMBER(p->p_sigacts->ps_sigignore, sig) || | ||||
SIGISMEMBER(td->td_sigmask, sig)) { | SIGISMEMBER(td->td_sigmask, sig)) { | ||||
/* Only allow them in write()/ioctl(). */ | /* Only allow them in write()/ioctl(). */ | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
PGRP_UNLOCK(pg); | |||||
return (sig == SIGTTOU ? 0 : EIO); | return (sig == SIGTTOU ? 0 : EIO); | ||||
} | } | ||||
pg = p->p_pgrp; | if ((p->p_flag & P_PPWAIT) != 0 || | ||||
if (p->p_flag & P_PPWAIT || pg->pg_jobc == 0) { | (pg->pg_flags & PGRP_ORPHANED) != 0) { | ||||
/* Don't allow the action to happen. */ | /* Don't allow the action to happen. */ | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
PGRP_UNLOCK(pg); | |||||
return (EIO); | return (EIO); | ||||
} | } | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
/* | /* | ||||
* Send the signal and sleep until we're the new | * Send the signal and sleep until we're the new | ||||
* foreground process group. | * foreground process group. | ||||
*/ | */ | ||||
if (sig != 0) { | if (sig != 0) { | ||||
ksiginfo_init(&ksi); | ksiginfo_init(&ksi); | ||||
ksi.ksi_code = SI_KERNEL; | ksi.ksi_code = SI_KERNEL; | ||||
ksi.ksi_signo = sig; | ksi.ksi_signo = sig; | ||||
sig = 0; | sig = 0; | ||||
} | } | ||||
PGRP_LOCK(pg); | |||||
/* | |||||
* pg may no longer be our process group. | |||||
* Re-check after locking process group. | |||||
*/ | |||||
PROC_LOCK(p); | |||||
if (p->p_pgrp != pg) { | |||||
PROC_UNLOCK(p); | |||||
PGRP_UNLOCK(pg); | |||||
continue; | |||||
} | |||||
PROC_UNLOCK(p); | |||||
pgsignal(pg, ksi.ksi_signo, 1, &ksi); | pgsignal(pg, ksi.ksi_signo, 1, &ksi); | ||||
PGRP_UNLOCK(pg); | PGRP_UNLOCK(pg); | ||||
error = tty_wait(tp, &tp->t_bgwait); | error = tty_wait(tp, &tp->t_bgwait); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,889 Lines • ▼ Show 20 Lines | DB_SHOW_COMMAND(tty, db_show_tty) | ||||
_db_show_termios("\ttermios_lock_in", &tp->t_termios_lock_in); | _db_show_termios("\ttermios_lock_in", &tp->t_termios_lock_in); | ||||
_db_show_termios("\ttermios_lock_out", &tp->t_termios_lock_out); | _db_show_termios("\ttermios_lock_out", &tp->t_termios_lock_out); | ||||
/* Hooks */ | /* Hooks */ | ||||
_db_show_devsw("\t", tp->t_devsw); | _db_show_devsw("\t", tp->t_devsw); | ||||
_db_show_hooks("\t", tp->t_hook); | _db_show_hooks("\t", tp->t_hook); | ||||
/* Process info. */ | /* Process info. */ | ||||
db_printf("\tpgrp: %p gid %d jobc %d\n", tp->t_pgrp, | db_printf("\tpgrp: %p gid %d\n", tp->t_pgrp, | ||||
tp->t_pgrp ? tp->t_pgrp->pg_id : 0, | tp->t_pgrp ? tp->t_pgrp->pg_id : 0); | ||||
tp->t_pgrp ? tp->t_pgrp->pg_jobc : 0); | |||||
db_printf("\tsession: %p", tp->t_session); | db_printf("\tsession: %p", tp->t_session); | ||||
if (tp->t_session != NULL) | if (tp->t_session != NULL) | ||||
db_printf(" count %u leader %p tty %p sid %d login %s", | db_printf(" count %u leader %p tty %p sid %d login %s", | ||||
tp->t_session->s_count, tp->t_session->s_leader, | tp->t_session->s_count, tp->t_session->s_leader, | ||||
tp->t_session->s_ttyp, tp->t_session->s_sid, | tp->t_session->s_ttyp, tp->t_session->s_sid, | ||||
tp->t_session->s_login); | tp->t_session->s_login); | ||||
db_printf("\n"); | db_printf("\n"); | ||||
db_printf("\tsessioncnt: %u\n", tp->t_sessioncnt); | db_printf("\tsessioncnt: %u\n", tp->t_sessioncnt); | ||||
▲ Show 20 Lines • Show All 46 Lines • Show Last 20 Lines |