- 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.
This commit is contained in:
Jeff Roberson 2003-03-31 23:30:41 +00:00
parent da4898b1d7
commit a447cd8b28
4 changed files with 179 additions and 6 deletions

View File

@ -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);

View File

@ -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
*/

View File

@ -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)

View File

@ -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);
/*