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