summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2003-03-31 23:30:41 +0000
committerjeff <jeff@FreeBSD.org>2003-03-31 23:30:41 +0000
commitb23496dd5426819dd9f0306b3f0271781e72ca94 (patch)
treef1fa75c8ce86783171186b3c3c3e7ffc669e2283
parent7e134f95f3b31d917bf5acfa4e8b81684ddd1076 (diff)
downloadFreeBSD-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.
-rw-r--r--include/signal.h2
-rw-r--r--sys/kern/kern_sig.c174
-rw-r--r--sys/kern/syscalls.master7
-rw-r--r--sys/sys/signalvar.h2
4 files changed, 179 insertions, 6 deletions
diff --git a/include/signal.h b/include/signal.h
index 572cad5..e869e1d 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 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)
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 0baa57e..a30125c 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);
/*
OpenPOWER on IntegriCloud