From ae915c6516751201fff5f2ee46a1c7895480f81b Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 29 Aug 2025 13:12:05 -0400 Subject: [PATCH] wayland: Add a sigtimedwait() implementation for OpenBSD sigtimedwait() is an optional part of POSIX.1-2001, and OpenBSD doesn't implement it. Add a replacement implementation based on https://comp.unix.programmer.narkive.com/rEDH0sPT/sigtimedwait-implementation (cherry picked from commit 1049426a765cc38e94f65a839b156852d86e3b57) --- CMakeLists.txt | 1 + include/build_config/SDL_build_config.h.cmake | 1 + src/video/wayland/SDL_waylanddatamanager.c | 44 ++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da7f72ae67..3256af51a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1101,6 +1101,7 @@ if(SDL_LIBC) check_symbol_exists(gethostname "unistd.h" HAVE_GETHOSTNAME) check_symbol_exists(getpagesize "unistd.h" HAVE_GETPAGESIZE) check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) + check_symbol_exists(sigtimedwait "signal.h" HAVE_SIGTIMEDWAIT) check_symbol_exists(setjmp "setjmp.h" HAVE_SETJMP) check_symbol_exists(nanosleep "time.h" HAVE_NANOSLEEP) check_symbol_exists(gmtime_r "time.h" HAVE_GMTIME_R) diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 6ce491e7d2..a2a2331a54 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -174,6 +174,7 @@ #cmakedefine HAVE_MEMFD_CREATE 1 #cmakedefine HAVE_POSIX_FALLOCATE 1 #cmakedefine HAVE_SIGACTION 1 +#cmakedefine HAVE_SIGTIMEDWAIT 1 #cmakedefine HAVE_SA_SIGACTION 1 #cmakedefine HAVE_ST_MTIM 1 #cmakedefine HAVE_SETJMP 1 diff --git a/src/video/wayland/SDL_waylanddatamanager.c b/src/video/wayland/SDL_waylanddatamanager.c index 6f5b32bbb3..767d1f030d 100644 --- a/src/video/wayland/SDL_waylanddatamanager.c +++ b/src/video/wayland/SDL_waylanddatamanager.c @@ -41,6 +41,48 @@ */ #define PIPE_TIMEOUT_NS SDL_MS_TO_NS(14) +/* sigtimedwait() is an optional part of POSIX.1-2001, and OpenBSD doesn't implement it. + * Based on https://comp.unix.programmer.narkive.com/rEDH0sPT/sigtimedwait-implementation + */ +#ifndef HAVE_SIGTIMEDWAIT +#include +#include +static int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) +{ + struct timespec elapsed = { 0 }, rem = { 0 }; + sigset_t pending; + + do { + // Check the pending signals, and call sigwait if there is at least one of interest in the set. + sigpending(&pending); + for (int signo = 1; signo < NSIG; ++signo) { + if (sigismember(set, signo) && sigismember(&pending, signo)) { + if (!sigwait(set, &signo)) { + if (info) { + SDL_memset(info, 0, sizeof *info); + info->si_signo = signo; + } + return signo; + } else { + return -1; + } + } + } + + if (timeout->tv_sec || timeout->tv_nsec) { + long ns = 20000000L; // 2/100ths of a 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; +} +#endif + static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_t *pos) { int ready = 0; @@ -76,7 +118,7 @@ static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_ } } - sigtimedwait(&sig_set, 0, &zerotime); + sigtimedwait(&sig_set, NULL, &zerotime); #ifdef SDL_THREADS_DISABLED sigprocmask(SIG_SETMASK, &old_sig_set, NULL);