diff options
author | luoqi <luoqi@FreeBSD.org> | 1999-10-11 20:33:17 +0000 |
---|---|---|
committer | luoqi <luoqi@FreeBSD.org> | 1999-10-11 20:33:17 +0000 |
commit | fd8b4427a5a052988cfb0778b779cff1a3e09628 (patch) | |
tree | 7cad9d7dad8a4c0a9a157153dada2dbbd270e491 /sys/kern | |
parent | 031a7ae6a88dcce6c4d95badfd6b19cbe5520d38 (diff) | |
download | FreeBSD-src-fd8b4427a5a052988cfb0778b779cff1a3e09628.zip FreeBSD-src-fd8b4427a5a052988cfb0778b779cff1a3e09628.tar.gz |
Add a per-signal flag to mark handlers registered with osigaction, so we
can provide the correct context to each signal handler.
Fix broken sigsuspend(): don't use p_oldsigmask as a flag, use SAS_OLDMASK
as we did before the linuxthreads support merge (submitted by bde).
Move ps_sigstk from to p_sigacts to the main proc structure since signal
stack should not be shared among threads.
Move SAS_OLDMASK and SAS_ALTSTACK flags from sigacts::ps_flags to proc::p_flag.
Move PS_NOCLDSTOP and PS_NOCLDWAIT flags from proc::p_flag to procsig::ps_flag.
Reviewed by: marcel, jdp, bde
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_exit.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_kthread.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 130 |
3 files changed, 71 insertions, 66 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index ccb6a02..c82eca2 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -307,11 +307,11 @@ exit1(p, rv) switchticks = ticks; /* - * Notify parent that we're gone. If parent has the P_NOCLDWAIT + * Notify parent that we're gone. If parent has the PS_NOCLDWAIT * flag set, notify process 1 instead (and hope it will handle * this situation). */ - if (p->p_pptr->p_procsig->ps_flag & P_NOCLDWAIT) { + if (p->p_pptr->p_procsig->ps_flag & PS_NOCLDWAIT) { struct proc *pp = p->p_pptr; proc_reparent(p, initproc); /* diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index f5b0c1d..b375fbb 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -76,7 +76,8 @@ kthread_create(void (*func)(void *), void *arg, *newpp = p2; /* this is a non-swapped system process */ - p2->p_flag |= P_INMEM | P_SYSTEM | P_NOCLDWAIT; + p2->p_flag |= P_INMEM | P_SYSTEM; + p2->p_procsig->ps_flag |= PS_NOCLDWAIT; PHOLD(p2); /* set up arg0 for 'ps', et al */ diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 3d3aaba..61cf219 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -71,9 +71,9 @@ static int sigprop __P((int sig)); static int sig_ffs __P((sigset_t *set)); static int killpg1 __P((struct proc *cp, int sig, int pgid, int all)); static int do_sigaction __P((struct proc *p, int sig, struct sigaction *act, - struct sigaction *oact)); + struct sigaction *oact, int old)); static int do_sigprocmask __P((struct proc *p, int how, sigset_t *set, - sigset_t *oset)); + sigset_t *oset, int old)); static void stop __P((struct proc *)); static char *expand_name __P((const char *, uid_t, pid_t)); static int coredump __P((struct proc *)); @@ -180,10 +180,11 @@ extern __inline int sig_ffs(sigset_t *set) * osigaction */ static int -do_sigaction(p, sig, act, oact) +do_sigaction(p, sig, act, oact, old) struct proc *p; register int sig; struct sigaction *act, *oact; + int old; { register struct sigacts *ps = p->p_sigacts; @@ -204,9 +205,9 @@ do_sigaction(p, sig, act, oact) oact->sa_flags |= SA_NODEFER; if (SIGISMEMBER(ps->ps_siginfo, sig)) oact->sa_flags |= SA_SIGINFO; - if (sig == SIGCHLD && p->p_procsig->ps_flag & P_NOCLDSTOP) + if (sig == SIGCHLD && p->p_procsig->ps_flag & PS_NOCLDSTOP) oact->sa_flags |= SA_NOCLDSTOP; - if (sig == SIGCHLD && p->p_procsig->ps_flag & P_NOCLDWAIT) + if (sig == SIGCHLD && p->p_procsig->ps_flag & PS_NOCLDWAIT) oact->sa_flags |= SA_NOCLDWAIT; } if (act) { @@ -254,9 +255,9 @@ do_sigaction(p, sig, act, oact) #endif if (sig == SIGCHLD) { if (act->sa_flags & SA_NOCLDSTOP) - p->p_procsig->ps_flag |= P_NOCLDSTOP; + p->p_procsig->ps_flag |= PS_NOCLDSTOP; else - p->p_procsig->ps_flag &= ~P_NOCLDSTOP; + p->p_procsig->ps_flag &= ~PS_NOCLDSTOP; if (act->sa_flags & SA_NOCLDWAIT) { /* * Paranoia: since SA_NOCLDWAIT is implemented @@ -265,11 +266,11 @@ do_sigaction(p, sig, act, oact) * is forbidden to set SA_NOCLDWAIT. */ if (p->p_pid == 1) - p->p_procsig->ps_flag &= ~P_NOCLDWAIT; + p->p_procsig->ps_flag &= ~PS_NOCLDWAIT; else - p->p_procsig->ps_flag |= P_NOCLDWAIT; + p->p_procsig->ps_flag |= PS_NOCLDWAIT; } else - p->p_procsig->ps_flag &= ~P_NOCLDWAIT; + p->p_procsig->ps_flag &= ~PS_NOCLDWAIT; } /* * Set bit in p_sigignore for signals that are set to SIG_IGN, @@ -286,14 +287,18 @@ do_sigaction(p, sig, act, oact) /* easier in psignal */ SIGADDSET(p->p_sigignore, sig); SIGDELSET(p->p_sigcatch, sig); - } - else { + } else { SIGDELSET(p->p_sigignore, sig); if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL) SIGDELSET(p->p_sigcatch, sig); else SIGADDSET(p->p_sigcatch, sig); } + if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || + ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL || !old) + SIGDELSET(ps->ps_osigset, sig); + else + SIGADDSET(ps->ps_osigset, sig); (void) spl0(); } @@ -317,8 +322,6 @@ sigaction(p, uap) register struct sigaction *actp, *oactp; int error; - p->p_flag |= P_NEWSIGSET; - actp = (uap->act) ? &act : NULL; oactp = (uap->oact) ? &oact : NULL; if (actp) { @@ -327,7 +330,7 @@ sigaction(p, uap) if (error) return (error); } - error = do_sigaction(p, uap->sig, actp, oactp); + error = do_sigaction(p, uap->sig, actp, oactp, 0); if (oactp && !error) { error = copyout((caddr_t)oactp, (caddr_t)uap->oact, sizeof(oact)); @@ -363,7 +366,7 @@ osigaction(p, uap) nsap->sa_flags = sa.sa_flags; OSIG2SIG(sa.sa_mask, nsap->sa_mask); } - error = do_sigaction(p, uap->signum, nsap, osap); + error = do_sigaction(p, uap->signum, nsap, osap, 1); if (osap && !error) { sa.sa_handler = osap->sa_handler; sa.sa_flags = osap->sa_flags; @@ -417,14 +420,13 @@ execsigs(p) * Reset stack state to the user stack. * Clear set of signals caught on the signal stack. */ - ps->ps_sigstk.ss_flags = SS_DISABLE; - ps->ps_sigstk.ss_size = 0; - ps->ps_sigstk.ss_sp = 0; - ps->ps_flags = 0; + p->p_sigstk.ss_flags = SS_DISABLE; + p->p_sigstk.ss_size = 0; + p->p_sigstk.ss_sp = 0; /* * Reset no zombies if child dies flag as Solaris does. */ - p->p_procsig->ps_flag &= ~P_NOCLDWAIT; + p->p_procsig->ps_flag &= ~PS_NOCLDWAIT; } /* @@ -434,10 +436,11 @@ execsigs(p) * the library stub does the rest. */ static int -do_sigprocmask(p, how, set, oset) +do_sigprocmask(p, how, set, oset, old) struct proc *p; int how; sigset_t *set, *oset; + int old; { int error; @@ -449,15 +452,18 @@ do_sigprocmask(p, how, set, oset) (void) splhigh(); switch (how) { case SIG_BLOCK: + SIG_CANTMASK(*set); SIGSETOR(p->p_sigmask, *set); - SIG_CANTMASK(p->p_sigmask); break; case SIG_UNBLOCK: SIGSETNAND(p->p_sigmask, *set); break; case SIG_SETMASK: - p->p_sigmask = *set; - SIG_CANTMASK(p->p_sigmask); + SIG_CANTMASK(*set); + if (old) + SIGSETLO(p->p_sigmask, *set); + else + p->p_sigmask = *set; break; default: error = EINVAL; @@ -492,7 +498,7 @@ sigprocmask(p, uap) if (error) return (error); } - error = do_sigprocmask(p, uap->how, setp, osetp); + error = do_sigprocmask(p, uap->how, setp, osetp, 0); if (osetp && !error) { error = copyout((caddr_t)osetp, (caddr_t)uap->oset, sizeof(oset)); @@ -515,7 +521,7 @@ osigprocmask(p, uap) int error; OSIG2SIG(uap->mask, set); - error = do_sigprocmask(p, uap->how, &set, &oset); + error = do_sigprocmask(p, uap->how, &set, &oset, 1); SIG2OSIG(oset, p->p_retval[0]); return (error); } @@ -588,7 +594,7 @@ osigvec(p, uap) nsap->sa_flags |= SA_USERTRAMP; #endif } - error = do_sigaction(p, uap->signum, nsap, osap); + error = do_sigaction(p, uap->signum, nsap, osap, 1); if (osap && !error) { vec.sv_handler = osap->sa_handler; SIG2OSIG(osap->sa_mask, vec.sv_mask); @@ -640,7 +646,7 @@ osigsetmask(p, uap) SIG_CANTMASK(set); (void) splhigh(); SIG2OSIG(p->p_sigmask, p->p_retval[0]); - p->p_sigmask = set; + SIGSETLO(p->p_sigmask, set); (void) spl0(); return (0); } @@ -671,15 +677,17 @@ sigsuspend(p, uap) return (error); /* - * When returning from sigpause, we want + * When returning from sigsuspend, we want * the old mask to be restored after the * signal handler has finished. Thus, we * save it here and mark the sigacts structure * to indicate this. */ p->p_oldsigmask = p->p_sigmask; + p->p_flag |= P_OLDMASK; + + SIG_CANTMASK(mask); p->p_sigmask = mask; - SIG_CANTMASK(p->p_sigmask); while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0) /* void */; /* always return EINTR rather than ERESTART... */ @@ -697,14 +705,15 @@ osigsuspend(p, uap) register struct proc *p; struct osigsuspend_args *uap; { - sigset_t set; + sigset_t mask; register struct sigacts *ps = p->p_sigacts; - OSIG2SIG(uap->mask, set); - SIG_CANTMASK(set); p->p_oldsigmask = p->p_sigmask; - p->p_sigmask = set; - while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0) + p->p_flag |= P_OLDMASK; + OSIG2SIG(uap->mask, mask); + SIG_CANTMASK(mask); + SIGSETLO(p->p_sigmask, mask); + while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "opause", 0) == 0) /* void */; /* always return EINTR rather than ERESTART... */ return (EINTR); @@ -724,21 +733,19 @@ osigstack(p, uap) register struct osigstack_args *uap; { struct sigstack ss; - struct sigacts *psp; int error = 0; - psp = p->p_sigacts; - ss.ss_sp = psp->ps_sigstk.ss_sp; - ss.ss_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; + ss.ss_sp = p->p_sigstk.ss_sp; + ss.ss_onstack = p->p_sigstk.ss_flags & SS_ONSTACK; if (uap->oss && (error = copyout((caddr_t)&ss, (caddr_t)uap->oss, sizeof (struct sigstack)))) return (error); if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss))) == 0) { - psp->ps_sigstk.ss_sp = ss.ss_sp; - psp->ps_sigstk.ss_size = 0; - psp->ps_sigstk.ss_flags |= ss.ss_onstack & SS_ONSTACK; - psp->ps_flags |= SAS_ALTSTACK; + p->p_sigstk.ss_sp = ss.ss_sp; + p->p_sigstk.ss_size = 0; + p->p_sigstk.ss_flags |= ss.ss_onstack & SS_ONSTACK; + p->p_flag |= P_ALTSTACK; } return (error); } @@ -756,14 +763,12 @@ sigaltstack(p, uap) struct proc *p; register struct sigaltstack_args *uap; { - struct sigacts *psp; stack_t ss; int error; - psp = p->p_sigacts; - if ((psp->ps_flags & SAS_ALTSTACK) == 0) - psp->ps_sigstk.ss_flags |= SS_DISABLE; - if (uap->oss && (error = copyout((caddr_t)&psp->ps_sigstk, + if ((p->p_flag & P_ALTSTACK) == 0) + p->p_sigstk.ss_flags |= SS_DISABLE; + if (uap->oss && (error = copyout((caddr_t)&p->p_sigstk, (caddr_t)uap->oss, sizeof (stack_t)))) return (error); if (uap->ss == 0) @@ -771,16 +776,16 @@ sigaltstack(p, uap) if ((error = copyin((caddr_t)uap->ss, (caddr_t)&ss, sizeof (ss)))) return (error); if (ss.ss_flags & SS_DISABLE) { - if (psp->ps_sigstk.ss_flags & SS_ONSTACK) + if (p->p_sigstk.ss_flags & SS_ONSTACK) return (EINVAL); - psp->ps_flags &= ~SAS_ALTSTACK; - psp->ps_sigstk.ss_flags = ss.ss_flags; + p->p_flag &= ~P_ALTSTACK; + p->p_sigstk.ss_flags = ss.ss_flags; return (0); } if (ss.ss_size < MINSIGSTKSZ) return (ENOMEM); - psp->ps_flags |= SAS_ALTSTACK; - psp->ps_sigstk = ss; + p->p_flag |= P_ALTSTACK; + p->p_sigstk = ss; return (0); } @@ -1093,7 +1098,7 @@ psignal(p, sig) goto out; SIGDELSET(p->p_siglist, sig); p->p_xstat = sig; - if ((p->p_pptr->p_procsig->ps_flag & P_NOCLDSTOP) == 0) + if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); stop(p); goto out; @@ -1300,7 +1305,7 @@ issignal(p) break; /* == ignore */ p->p_xstat = sig; stop(p); - if ((p->p_pptr->p_procsig->ps_flag & P_NOCLDSTOP) == 0) + if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); mi_switch(); break; @@ -1372,8 +1377,7 @@ postsig(sig) action = ps->ps_sigact[_SIG_IDX(sig)]; #ifdef KTRACE if (KTRPOINT(p, KTR_PSIG)) - ktrpsig(p->p_tracep, - sig, action, SIGNOTEMPTY(p->p_oldsigmask) ? + ktrpsig(p->p_tracep, sig, action, p->p_flag & P_OLDMASK ? &p->p_oldsigmask : &p->p_sigmask, 0); #endif STOPEVENT(p, S_SIG, sig); @@ -1393,17 +1397,17 @@ postsig(sig) ("postsig action")); /* * Set the new mask value and also defer further - * occurences of this signal. + * occurrences of this signal. * - * Special case: user has done a sigpause. Here the + * Special case: user has done a sigsuspend. Here the * current mask is not of interest, but rather the - * mask from before the sigpause is what we want + * mask from before the sigsuspend is what we want * restored after the signal processing is completed. */ (void) splhigh(); - if (SIGNOTEMPTY(p->p_oldsigmask)) { + if (p->p_flag & P_OLDMASK) { returnmask = p->p_oldsigmask; - SIGEMPTYSET(p->p_oldsigmask); + p->p_flag &= ~P_OLDMASK; } else returnmask = p->p_sigmask; |