Ugh, macOS doesn't support timer_create() and friends :| (Even up to 10.13, it seems; not sure about 10.14!) Switch back to setitimer(). Also rename oldsig to prevSig and remove a needless (for now???) cast.

This commit is contained in:
Pietro Gagliardi 2019-05-04 14:24:22 -04:00
parent 8655bbf19c
commit 5836a2a236
2 changed files with 24 additions and 39 deletions

View File

@ -12,15 +12,10 @@ if libui_OS == 'windows'
'testing_windows.c', 'testing_windows.c',
'timer_windows.c', 'timer_windows.c',
] ]
elif libui_OS == 'darwin'
libui_test_sources += [
'testing_darwin.c',
'testing_darwinunix.c',
]
else else
libui_test_sources += [ libui_test_sources += [
'testing_darwinunix.c', 'testing_darwinunix.c',
'testing_unix.c', 'timer_darwinunix.c'
] ]
endif endif

View File

@ -73,7 +73,7 @@ timerTime timerMonotonicNow(void)
ts.tv_nsec -= base.tv_nsec; ts.tv_nsec -= base.tv_nsec;
if (ts.tv_nsec < 0) { // this is safe because POSIX requires this to be of type long if (ts.tv_nsec < 0) { // this is safe because POSIX requires this to be of type long
ts.tv_sec--; ts.tv_sec--;
ts.tv_nsec += (long) timerSecond; ts.tv_nsec += timerSecond;
} }
ret = ((timerTime) (ts.tv_sec)) * timerSecond; ret = ((timerTime) (ts.tv_sec)) * timerSecond;
ret += (timerTime) (ts.tv_nsec); ret += (timerTime) (ts.tv_nsec);
@ -89,8 +89,8 @@ timerDuration timerTimeSub(timerTime end, timerTime start)
struct timeoutParams { struct timeoutParams {
jmp_buf retpos; jmp_buf retpos;
timer_t timer; struct itimerval prevDuration;
struct sigaction oldsig; struct sigaction prevSig;
}; };
static struct timeoutParams p; static struct timeoutParams p;
@ -100,20 +100,20 @@ static void onTimeout(int sig, siginfo_t *info, void *ctx)
if (info->si_value.sival_ptr == &p) if (info->si_value.sival_ptr == &p)
longjmp(p.retpos, 1); longjmp(p.retpos, 1);
// otherwise, call the overloaded SIGALRM handler // otherwise, call the overloaded SIGALRM handler
if ((p.oldsig.sa_flags & SA_SIGINFO) != 0) { if ((p.prevSig.sa_flags & SA_SIGINFO) != 0) {
(*(p.oldsig.sa_sigaction))(sig, info, ctx); (*(p.prevSig.sa_sigaction))(sig, info, ctx);
return; return;
} }
if (p.oldsig.sa_handler == SIG_IGN) if (p.prevSig.sa_handler == SIG_IGN)
return; return;
if (p.oldsig.sa_handler == SIG_DFL) { if (p.prevSig.sa_handler == SIG_DFL) {
// SIG_DFL for SIGALRM is to terminate the program // SIG_DFL for SIGALRM is to terminate the program
// because POSIX doesn't specify how to convert from signal number to exit code, we will have to do this instead // because POSIX doesn't specify how to convert from signal number to exit code, we will have to do this instead
// (POSIX does say these should be safe to call unless the signal was explicitly raised, which we aren't doing, and timer_create() isn't documented as doing that either...) // (POSIX does say these should be safe to call unless the signal was explicitly raised, which we aren't doing, and timer_create() isn't documented as doing that either...)
signal(sig, SIG_DFL); signal(sig, SIG_DFL);
raise(sig); raise(sig);
} }
(*(p.oldsig.sa_handler))(sig); (*(p.prevSig.sa_handler))(sig);
} }
// POSIX doesn't have atomic operations :| // POSIX doesn't have atomic operations :|
@ -172,11 +172,10 @@ timerSysError timerRunWithTimeout(timerDuration d, void (*f)(void *data), void *
sigset_t sigalrm, allsigs; sigset_t sigalrm, allsigs;
sigset_t prevMask; sigset_t prevMask;
volatile int restorePrevMask = 0; volatile int restorePrevMask = 0;
struct sigevent event;
volatile int destroyTimer = 0;
struct sigaction sig; struct sigaction sig;
volatile int restoreSignal = 0; volatile int restoreSignal = 0;
struct itimerspec duration; struct itimerval duration;
volatile int destroyTimer = 0;
int err = 0; int err = 0;
*timedOut = 0; *timedOut = 0;
@ -201,37 +200,28 @@ timerSysError timerRunWithTimeout(timerDuration d, void (*f)(void *data), void *
return (timerSysError) err; return (timerSysError) err;
restorePrevMask = 1; restorePrevMask = 1;
memset(&event, 0, sizeof (struct sigevent));
event.sigev_notify = SIGEV_SIGNAL;
event.sigev_signo = SIGALRM;
event.sigev_value.sival_ptr = &p;
errno = 0;
if (timer_create(CLOCK_REALTIME, &event, &(p.timer)) != 0) {
err = errno;
goto out;
}
destroyTimer = 1;
if (setjmp(p.retpos) == 0) { if (setjmp(p.retpos) == 0) {
sig.sa_mask = &allsigs; sig.sa_mask = allsigs;
sig.sa_flags = SA_SIGINFO; sig.sa_flags = SA_SIGINFO;
sig.sa_sigaction = onTimeout; sig.sa_sigaction = onTimeout;
errno = 0; errno = 0;
if (sigaction(SIGALRM, &sig, &(p.oldsig)) != 0) { if (sigaction(SIGALRM, &sig, &(p.prevSig)) != 0) {
err = errno; err = errno;
goto out; goto out;
} }
restoreSignal = 1; restoreSignal = 1;
duration.it_interval.tv_sec = 0; duration.it_interval.tv_sec = 0;
duration.it_interval.tv_nsec = 0; duration.it_interval.tv_usec = 0;
duration.it_value.tv_sec = d / testingNsecPerSec; duration.it_value.tv_sec = d / timerSecond;
duration.it_value.tv_nsec = d % testingNsecPerSec; duration.it_value.tv_usec = (d % timerSecond) / timerMicrosecond;
errno = 0; errno = 0;
if (timer_settimer(p.timer, 0, &duration, NULL) != 0) { if (setitimer(ITIMER_REAL, &duration, &(p.prevDuration)) != 0) {
err = errno; err = errno;
goto out; goto out;
} }
destroyTimer = 1;
// and fire away // and fire away
err = pthread_sigmask(SIG_UNBLOCK, &sigalrm, NULL); err = pthread_sigmask(SIG_UNBLOCK, &sigalrm, NULL);
if (err != 0) if (err != 0)
@ -243,10 +233,10 @@ timerSysError timerRunWithTimeout(timerDuration d, void (*f)(void *data), void *
err = 0; err = 0;
out: out:
if (restoreSignal)
sigaction(SIGALRM, &(p.oldsig), NULL);
if (destroyTimer) if (destroyTimer)
timer_delete(p.timer); setitimer(ITIMER_REAL, &(p.prevDuration), NULL);
if (restoreSignal)
sigaction(SIGALRM, &(p.prevSig), NULL);
if (restorePrevMask) if (restorePrevMask)
pthread_sigmask(SIG_SETMASK, &prevMask, NULL); pthread_sigmask(SIG_SETMASK, &prevMask, NULL);
teardownNonReentrance(); teardownNonReentrance();
@ -258,8 +248,8 @@ timerSysError timerSleep(timerDuration d)
struct timespec duration, remaining; struct timespec duration, remaining;
int err; int err;
duration.tv_sec = d / testingNsecPerSec; duration.tv_sec = d / timerSecond;
duration.tv_nsec = d % testingNsecPerSec; duration.tv_nsec = d % timerSecond;
for (;;) { for (;;) {
errno = 0; errno = 0;
if (nanosleep(&duration, &remaining) == 0) if (nanosleep(&duration, &remaining) == 0)