William Ahern
2011-12-09 21:41:32 UTC
Anyone spot any noteworthy issues in this implementation, other than
siginfo_t not being filled out completely and the use NSIG?
It seemed more convenient to write this than refactor the code relying on
the interface. I've tested this on OS X and OpenBSD and it seems to work.
I suppose it also doesn't handle EINTR correctly, but I can live with that.
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) {
struct timespec elapsed = { 0, 0 }, rem;
sigset_t pending;
int signo;
long ns;
do {
sigpending(&pending); /* doesn't clear pending queue */
for (signo = 1; signo < NSIG; signo++) {
if (sigismember(set, signo) && sigismember(&pending, signo)) {
if (info) {
memset(info, 0, sizeof *info);
info->si_signo = signo;
}
return signo;
}
}
ns = 200000000L; /* 2/10th second */
nanosleep(&(struct timespec){ 0, ns }, &rem);
ns -= rem.tv_nsec;
elapsed.tv_sec += (elapsed.tv_nsec + ns) / 1000000000L;
elapsed.tv_nsec = (elapsed.tv_nsec + ns) % 1000000000L;
} while (elapsed.tv_sec < timeout->tv_sec || (elapsed.tv_sec == timeout->tv_sec && elapsed.tv_nsec < timeout->tv_nsec));
errno = EAGAIN;
return -1;
} /* sigtimedwait() */
siginfo_t not being filled out completely and the use NSIG?
It seemed more convenient to write this than refactor the code relying on
the interface. I've tested this on OS X and OpenBSD and it seems to work.
I suppose it also doesn't handle EINTR correctly, but I can live with that.
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) {
struct timespec elapsed = { 0, 0 }, rem;
sigset_t pending;
int signo;
long ns;
do {
sigpending(&pending); /* doesn't clear pending queue */
for (signo = 1; signo < NSIG; signo++) {
if (sigismember(set, signo) && sigismember(&pending, signo)) {
if (info) {
memset(info, 0, sizeof *info);
info->si_signo = signo;
}
return signo;
}
}
ns = 200000000L; /* 2/10th second */
nanosleep(&(struct timespec){ 0, ns }, &rem);
ns -= rem.tv_nsec;
elapsed.tv_sec += (elapsed.tv_nsec + ns) / 1000000000L;
elapsed.tv_nsec = (elapsed.tv_nsec + ns) % 1000000000L;
} while (elapsed.tv_sec < timeout->tv_sec || (elapsed.tv_sec == timeout->tv_sec && elapsed.tv_nsec < timeout->tv_nsec));
errno = EAGAIN;
return -1;
} /* sigtimedwait() */