From a447cd8b287c5c3557278ece86822d2db4d71768 Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Mon, 31 Mar 2003 23:30:41 +0000 Subject: [PATCH] - Define sigwait, sigtimedwait, and sigwaitinfo in terms of kern_sigtimedwait() which is capable of supporting all of their semantics. - These should be POSIX compliant but more careful review is needed before we announce this. --- include/signal.h | 2 +- sys/kern/kern_sig.c | 174 ++++++++++++++++++++++++++++++++++++++- sys/kern/syscalls.master | 7 +- sys/sys/signalvar.h | 2 - 4 files changed, 179 insertions(+), 6 deletions(-) diff --git a/include/signal.h b/include/signal.h index 572cad58949e..e869e1dd0521 100644 --- a/include/signal.h +++ b/include/signal.h @@ -85,12 +85,12 @@ int sigwait(const sigset_t * __restrict, int * __restrict); * in scope (in the current implementation), so we can't use it here. */ int sigqueue(__pid_t, int, const union sigval); +#endif struct timespec; int sigtimedwait(const sigset_t * __restrict, siginfo_t * __restrict, const struct timespec * __restrict); int sigwaitinfo(const sigset_t * __restrict, siginfo_t * __restrict); #endif -#endif #if __XSI_VISIBLE int killpg(__pid_t, int); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index ee2b7ec9fce1..116a6108aead 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -89,6 +89,10 @@ static int filt_sigattach(struct knote *kn); static void filt_sigdetach(struct knote *kn); static int filt_signal(struct knote *kn, long hint); static struct thread *sigtd(struct proc *p, int sig, int prop); +static int do_sigprocmask(struct thread *td, int how, + sigset_t *set, sigset_t *oset, int old); +static int kern_sigtimedwait(struct thread *td, sigset_t set, + siginfo_t *info, struct timespec *timeout); struct filterops sig_filtops = { 0, filt_sigattach, filt_sigdetach, filt_signal }; @@ -592,7 +596,7 @@ execsigs(p) * * Manipulate signal mask. */ -int +static int do_sigprocmask(td, how, set, oset, old) struct thread *td; int how; @@ -694,9 +698,177 @@ osigprocmask(td, uap) #ifndef _SYS_SYSPROTO_H_ struct sigpending_args { + SIGSETOR(siglist, td->td_siglist); sigset_t *set; }; #endif +/* + * MPSAFE + */ +int +sigwait(struct thread *td, struct sigwait_args *uap) +{ + siginfo_t info; + sigset_t set; + int error; + + error = copyin(uap->set, &set, sizeof(set)); + if (error) + return (error); + + error = kern_sigtimedwait(td, set, &info, NULL); + if (error) + return (error); + + error = copyout(&info.si_signo, uap->sig, sizeof(info.si_signo)); + /* Repost if we got an error. */ + if (error && info.si_signo) + tdsignal(td, info.si_signo); + + return (error); +} +/* + * MPSAFE + */ +int +sigtimedwait(struct thread *td, struct sigtimedwait_args *uap) +{ + struct timespec ts; + struct timespec *timeout; + sigset_t set; + siginfo_t info; + int error; + + if (uap->timeout) { + error = copyin(uap->timeout, &ts, sizeof(ts)); + if (error) + return (error); + + timeout = &ts; + } else + timeout = NULL; + + error = copyin(uap->set, &set, sizeof(set)); + if (error) + return (error); + + error = kern_sigtimedwait(td, set, &info, timeout); + if (error) + return (error); + + error = copyout(&info, uap->info, sizeof(info)); + /* Repost if we got an error. */ + if (error && info.si_signo) + tdsignal(td, info.si_signo); + + return (error); +} + +/* + * MPSAFE + */ +int +sigwaitinfo(struct thread *td, struct sigwaitinfo_args *uap) +{ + siginfo_t info; + sigset_t set; + int error; + + error = copyin(uap->set, &set, sizeof(set)); + if (error) + return (error); + + error = kern_sigtimedwait(td, set, &info, NULL); + if (error) + return (error); + + error = copyout(&info, uap->info, sizeof(info)); + /* Repost if we got an error. */ + if (error && info.si_signo) + tdsignal(td, info.si_signo); + + return (error); +} + +static int +kern_sigtimedwait(struct thread *td, sigset_t set, siginfo_t *info, + struct timespec *timeout) +{ + register struct sigacts *ps; + sigset_t oldmask; + struct proc *p; + int error; + int sig; + int hz; + + p = td->td_proc; + error = 0; + sig = 0; + SIG_CANTMASK(set); + + mtx_lock(&Giant); + PROC_LOCK(p); + + ps = p->p_sigacts; + oldmask = td->td_sigmask; + td->td_sigmask = set; + signotify(td); + + sig = cursig(td); + if (sig) + goto out; + + /* + * POSIX says this must be checked after looking for pending + * signals. + */ + if (timeout) { + struct timeval tv; + + if (timeout->tv_nsec > 1000000000) { + error = EINVAL; + goto out; + } + TIMESPEC_TO_TIMEVAL(&tv, timeout); + hz = tvtohz(&tv); + } else + hz = 0; + + error = msleep(ps, &p->p_mtx, PPAUSE|PCATCH, "pause", hz); + if (error == EINTR) + error = 0; + else if (error) + goto out; + + sig = cursig(td); +out: + td->td_sigmask = oldmask; + if (sig) { + sig_t action; + + action = ps->ps_sigact[_SIG_IDX(sig)]; +#ifdef KTRACE + if (KTRPOINT(td, KTR_PSIG)) + ktrpsig(sig, action, td->td_flags & TDF_OLDMASK ? + &td->td_oldsigmask : &td->td_sigmask, 0); +#endif + _STOPEVENT(p, S_SIG, sig); + + if (action == SIG_DFL) + sigexit(td, sig); + /* NOTREACHED */ + + SIGDELSET(td->td_siglist, sig); + info->si_signo = sig; + info->si_code = 0; + } + + PROC_UNLOCK(p); + mtx_unlock(&Giant); + + return (error); +} + /* * MPSAFE */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 10981a0cf8b9..088da7240e0a 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -494,8 +494,10 @@ struct sigaction *oact); } 343 MSTD POSIX { int sigpending(sigset_t *set); } 344 MCOMPAT4 BSD { int sigreturn(const struct ucontext4 *sigcntxp); } -345 UNIMPL NOHIDE sigtimedwait -346 UNIMPL NOHIDE sigwaitinfo +345 MSTD NOHIDE { int sigtimedwait(const sigset_t *set, \ + siginfo_t *info, const struct timespec *timeout); } +346 MSTD NOHIDE { int sigwaitinfo(const sigset_t *set, \ + siginfo_t *info); } 347 MSTD BSD { int __acl_get_file(const char *path, \ acl_type_t type, struct acl *aclp); } 348 MSTD BSD { int __acl_set_file(const char *path, \ @@ -621,6 +623,7 @@ acl_type_t type); } 428 MSTD BSD { int __acl_aclcheck_link(const char *path, \ acl_type_t type, struct acl *aclp); } +429 MSTD NOHIDE { int sigwait(const sigset_t *set, int *sig); } ; Please copy any additions and changes to the following compatability tables: ; sys/ia64/ia32/syscalls.master (take a best guess) diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 0baa57e06780..a30125c9732f 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -249,8 +249,6 @@ void sigexit(struct thread *td, int signum) __dead2; void siginit(struct proc *p); void signotify(struct thread *td); void trapsignal(struct thread *td, int sig, u_long code); -int do_sigprocmask(struct thread *td, int how, - sigset_t *set, sigset_t *oset, int old); int sig_ffs(sigset_t *set); /*