Ver código fonte

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
Frank Praznik 2 semanas atrás
pai
commit
1049426a76

+ 1 - 0
CMakeLists.txt

@@ -1126,6 +1126,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)

+ 1 - 0
include/build_config/SDL_build_config.h.cmake

@@ -180,6 +180,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

+ 43 - 1
src/video/wayland/SDL_waylanddatamanager.c

@@ -42,6 +42,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 <errno.h>
+#include <time.h>
+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;
@@ -77,7 +119,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);