Don't restart a timeout wait in kern_sigtimedwait, also allow it

to wait longer than a single integer can represent.
This commit is contained in:
David Xu 2005-02-19 06:05:49 +00:00
parent 7a5147540a
commit 1089f0319b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=142072

View file

@ -846,10 +846,9 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
struct sigacts *ps;
sigset_t savedmask, sigset;
struct proc *p;
int error;
int sig;
int hz;
int i;
int error, sig, hz, i, timevalid = 0;
struct timespec rts, ets, ts;
struct timeval tv;
p = td->td_proc;
error = 0;
@ -859,6 +858,14 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
PROC_LOCK(p);
ps = p->p_sigacts;
savedmask = td->td_sigmask;
if (timeout) {
if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) {
timevalid = 1;
getnanouptime(&rts);
ets = rts;
timespecadd(&ets, timeout);
}
}
again:
for (i = 1; i <= _SIG_MAXSIG; ++i) {
@ -909,17 +916,18 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
* signals.
*/
if (timeout) {
struct timeval tv;
if (timeout->tv_nsec < 0 || timeout->tv_nsec > 1000000000) {
if (!timevalid) {
error = EINVAL;
goto out;
}
if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
getnanouptime(&rts);
if (timespeccmp(&rts, &ets, >=)) {
error = EAGAIN;
goto out;
}
TIMESPEC_TO_TIMEVAL(&tv, timeout);
ts = ets;
timespecsub(&ts, &rts);
TIMESPEC_TO_TIMEVAL(&tv, &ts);
hz = tvtohz(&tv);
} else
hz = 0;
@ -927,8 +935,15 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
td->td_waitset = &waitset;
error = msleep(&ps, &p->p_mtx, PPAUSE|PCATCH, "sigwait", hz);
td->td_waitset = NULL;
if (error == 0) /* surplus wakeup ? */
error = EINTR;
if (timeout) {
if (error == ERESTART) {
/* timeout can not be restarted. */
error = EINTR;
} else if (error == EAGAIN) {
/* will calculate timeout by ourself. */
error = 0;
}
}
goto again;
out:
@ -946,6 +961,7 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
_STOPEVENT(p, S_SIG, sig);
SIGDELSET(td->td_siglist, sig);
bzero(info, sizeof(*info));
info->si_signo = sig;
info->si_code = 0;
}