diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-03-15 00:20:57 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-03-15 23:15:11 +0100 |
commit | bafdc8f59ce010d239d84600418565a8e58cd021 (patch) | |
tree | 0d781174455cee1d8f5e92ca46aad51a568c04d9 /lib.c | |
parent | ada15857b058e360a04392171813f50470a36db3 (diff) |
lib: add naive sigtimedwait() stub for OS X
OS X does not implement `sigtimedwait()` used by `uc_system()` - add a
simple implementation of it.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 101 |
1 files changed, 101 insertions, 0 deletions
@@ -2261,6 +2261,107 @@ uc_warn(uc_vm_t *vm, size_t nargs) return uc_print_common(vm, nargs, stderr); } +#ifdef __APPLE__ +/* + * sigtimedwait() implementation based on + * https://comp.unix.programmer.narkive.com/rEDH0sPT/sigtimedwait-implementation + * and + * https://github.com/wahern/lunix/blob/master/src/unix.c + */ +static void +sigtimedwait_consume_signal(int signo) +{ +} + +static int +sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) +{ + struct timespec elapsed = { 0, 0 }, sleep, rem; + sigset_t pending, unblock, omask; + struct sigaction sa, osa; + int signo; + bool lt; + + while (true) { + sigemptyset(&pending); + sigpending(&pending); + + for (signo = 1; signo < NSIG; signo++) { + if (!sigismember(set, signo) || !sigismember(&pending, signo)) + continue; + + sa.sa_handler = sigtimedwait_consume_signal; + sa.sa_flags = 0; + sigfillset(&sa.sa_mask); + + sigaction(signo, &sa, &osa); + + sigemptyset(&unblock); + sigaddset(&unblock, signo); + sigprocmask(SIG_UNBLOCK, &unblock, &omask); + sigprocmask(SIG_SETMASK, &omask, NULL); + + sigaction(signo, &osa, NULL); + + if (info) { + memset(info, 0, sizeof(*info)); + info->si_signo = signo; + } + + return signo; + } + + sleep.tv_sec = 0; + sleep.tv_nsec = 200000000L; /* 2/10th second */ + rem = sleep; + + if (nanosleep(&sleep, &rem) == 0) { + elapsed.tv_sec += sleep.tv_sec; + elapsed.tv_nsec += sleep.tv_nsec; + + if (elapsed.tv_nsec > 1000000000) { + elapsed.tv_sec++; + elapsed.tv_nsec -= 1000000000; + } + } + else if (errno == EINTR) { + sleep.tv_sec -= rem.tv_sec; + sleep.tv_nsec -= rem.tv_nsec; + + if (sleep.tv_nsec < 0) { + sleep.tv_sec--; + sleep.tv_nsec += 1000000000; + } + + elapsed.tv_sec += sleep.tv_sec; + elapsed.tv_nsec += sleep.tv_nsec; + + if (elapsed.tv_nsec > 1000000000) { + elapsed.tv_sec++; + elapsed.tv_nsec -= 1000000000; + } + } + else { + return errno; + } + + lt = timeout + ? ((elapsed.tv_sec == timeout->tv_sec) + ? (elapsed.tv_nsec < timeout->tv_nsec) + : (elapsed.tv_sec < timeout->tv_sec)) + : true; + + if (!lt) + break; + } + + errno = EAGAIN; + + return -1; +} + +#endif + static uc_value_t * uc_system(uc_vm_t *vm, size_t nargs) { |