]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
io-util: Drop faulty assumption that poll flags == epoll flags
authorDaan De Meyer <daan@amutable.com>
Sat, 23 May 2026 10:33:12 +0000 (10:33 +0000)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 24 May 2026 18:36:43 +0000 (20:36 +0200)
Not the case on the sparc architecture. Replace with two translation
functions. The poll to epoll variant isn't used yet but will be used
when we add io-uring support to sd-event so we already add it here so
that it is in place.

Follow-up for cf4c65afa86021a750de38bbed192eeb1c9fd425

src/basic/io-util.c
src/basic/io-util.h
src/libsystemd/sd-future/fiber-io.c

index 3dbc3670a4a857dcfae8e9d88c726e2fc2ed33e9..d4a95128c850dd06a0ce94a30288a737a7518eda 100644 (file)
 #include "io-util.h"
 #include "time-util.h"
 
-/* EPOLL_POLL_COMMON_MASK in io-util.h treats POLL* and EPOLL* as interchangeable; verify it. */
-assert_cc((uint32_t) POLLIN    == EPOLLIN);
-assert_cc((uint32_t) POLLOUT   == EPOLLOUT);
-assert_cc((uint32_t) POLLERR   == EPOLLERR);
-assert_cc((uint32_t) POLLHUP   == EPOLLHUP);
-assert_cc((uint32_t) POLLPRI   == EPOLLPRI);
-assert_cc((uint32_t) POLLRDHUP == EPOLLRDHUP);
+uint32_t poll_events_to_epoll(uint32_t events) {
+        return (events & POLLIN    ? EPOLLIN    : 0) |
+               (events & POLLOUT   ? EPOLLOUT   : 0) |
+               (events & POLLPRI   ? EPOLLPRI   : 0) |
+               (events & POLLERR   ? EPOLLERR   : 0) |
+               (events & POLLHUP   ? EPOLLHUP   : 0) |
+               (events & POLLRDHUP ? EPOLLRDHUP : 0);
+}
+
+uint32_t epoll_events_to_poll(uint32_t events) {
+        return (events & EPOLLIN    ? POLLIN    : 0) |
+               (events & EPOLLOUT   ? POLLOUT   : 0) |
+               (events & EPOLLPRI   ? POLLPRI   : 0) |
+               (events & EPOLLERR   ? POLLERR   : 0) |
+               (events & EPOLLHUP   ? POLLHUP   : 0) |
+               (events & EPOLLRDHUP ? POLLRDHUP : 0);
+}
 
 int flush_fd(int fd) {
         int count = 0;
index ab52dc8db6506d9ae8df3cbc9898c0e2e51c9bd8..6697f88b546118d2aeb9acf81c4b856e09d9b16e 100644 (file)
@@ -3,11 +3,12 @@
 
 #include "basic-forward.h"
 
-/* The intersection of poll() and epoll_wait() event masks. Linux defines POLL* and EPOLL* with the
- * same numeric values for these — see the assert_cc()s in io-util.c — so this mask can be used
- * interchangeably as a `revents` (poll) or `events` (epoll) bitset. */
-#define EPOLL_POLL_COMMON_MASK \
-        (EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLRDHUP)
+/* On most architectures POLL* and EPOLL* share numeric values, but sparc allocates POLLRDHUP at
+ * 0x800 while EPOLLRDHUP is 0x2000 everywhere. Always go through these helpers when crossing
+ * between poll() and epoll() event masks. Bits outside the mapped set (EPOLLET, EPOLLONESHOT,
+ * POLLNVAL, …) are dropped. */
+uint32_t poll_events_to_epoll(uint32_t events);
+uint32_t epoll_events_to_poll(uint32_t events);
 
 int flush_fd(int fd);
 
index 823e8907185c51cf4f1984d50e2577971ff7d125..9fe0acfccd5e8f575f3f625244be2fefb3374428 100644 (file)
@@ -410,7 +410,7 @@ int sd_fiber_ppoll(struct pollfd *fds, size_t n_fds, const struct timespec *time
                 if (fds[i].fd < 0)
                         continue;
 
-                uint32_t events = fds[i].events & EPOLL_POLL_COMMON_MASK;
+                uint32_t events = poll_events_to_epoll(fds[i].events);
                 if (events == 0)
                         continue;