diff options
author | jeff <jeff@FreeBSD.org> | 2003-03-31 23:30:41 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2003-03-31 23:30:41 +0000 |
commit | b23496dd5426819dd9f0306b3f0271781e72ca94 (patch) | |
tree | f1fa75c8ce86783171186b3c3c3e7ffc669e2283 /sys/kern | |
parent | 7e134f95f3b31d917bf5acfa4e8b81684ddd1076 (diff) | |
download | FreeBSD-src-b23496dd5426819dd9f0306b3f0271781e72ca94.zip FreeBSD-src-b23496dd5426819dd9f0306b3f0271781e72ca94.tar.gz |
- 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.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_sig.c | 174 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 7 |
2 files changed, 178 insertions, 3 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index ee2b7ec..116a610 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,6 +698,7 @@ osigprocmask(td, uap) #ifndef _SYS_SYSPROTO_H_ struct sigpending_args { + SIGSETOR(siglist, td->td_siglist); sigset_t *set; }; #endif @@ -701,6 +706,173 @@ struct sigpending_args { * 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 + */ +int sigpending(td, uap) struct thread *td; struct sigpending_args *uap; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 10981a0..088da72 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) |